From 80aea03d46272a47dd7e9ba5f98a70f2d67cfd84 Mon Sep 17 00:00:00 2001
From: John Spurlock
Date: Wed, 18 Jul 2012 10:05:03 -0400
Subject: [PATCH 01/18] Fix systemui crash on Xoom startup
Make new bugdroid drawable available to non-hdpi device builds.
(moved to no-dpi for now)
It was getting optimized out during the build process.
Bug: 6828023
Change-Id: I31ac6ce2f50edc7f65d37b4b0f7513dd33a8b22d
---
.../{drawable-hdpi => drawable-nodpi}/bugdroid.png | Bin
1 file changed, 0 insertions(+), 0 deletions(-)
rename packages/SystemUI/res/{drawable-hdpi => drawable-nodpi}/bugdroid.png (100%)
diff --git a/packages/SystemUI/res/drawable-hdpi/bugdroid.png b/packages/SystemUI/res/drawable-nodpi/bugdroid.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/bugdroid.png
rename to packages/SystemUI/res/drawable-nodpi/bugdroid.png
From a70074ee4b32aa99ff55ba01c321194b9f5f83e6 Mon Sep 17 00:00:00 2001
From: Marco Nelissen
Date: Wed, 9 Jan 2013 09:46:54 -0800
Subject: [PATCH 02/18] Fix media scan NPE
b/7966288
Change-Id: I066bc9f00bccf070332d87d6f1bf3d6054b31136
---
media/java/android/media/MediaScanner.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index fbbcb0a323e58..7768a61968b56 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -958,7 +958,9 @@ public class MediaScanner
// If the rowId of the inserted file is needed, it gets inserted immediately,
// bypassing the bulk inserter.
if (inserter == null || needToSetSettings) {
- inserter.flushAll();
+ if (inserter != null) {
+ inserter.flushAll();
+ }
result = mMediaProvider.insert(tableUri, values);
} else if (entry.mFormat == MtpConstants.FORMAT_ASSOCIATION) {
inserter.insertwithPriority(tableUri, values);
From b225548244cd79ad251194a6b1975350ba8bdfe5 Mon Sep 17 00:00:00 2001
From: Nick Kralevich
Date: Wed, 9 Jan 2013 15:54:56 -0800
Subject: [PATCH 03/18] Revert "App home directories are now 0700 for
targetSdkVersion > 17"
This reverts commit 92091fa9636403728fe94cc83400495a8612c2d3.
Bug: 7966399
Bug: 7208882
---
api/current.txt | 1 -
core/java/android/content/Context.java | 96 ++++++-------------
core/java/android/os/Build.java | 11 ---
.../java/com/android/server/pm/Installer.java | 18 +---
.../server/pm/PackageManagerService.java | 19 ++--
.../java/com/android/server/pm/Settings.java | 6 +-
6 files changed, 45 insertions(+), 106 deletions(-)
diff --git a/api/current.txt b/api/current.txt
index e4d5fd1f188c1..cf24f1347e51c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15737,7 +15737,6 @@ package android.os {
field public static final int ICE_CREAM_SANDWICH_MR1 = 15; // 0xf
field public static final int JELLY_BEAN = 16; // 0x10
field public static final int JELLY_BEAN_MR1 = 17; // 0x11
- field public static final int K = 10000; // 0x2710
}
public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 257f84ef8e942..7aa2507975dc2 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -64,44 +64,30 @@ public abstract class Context {
*/
public static final int MODE_PRIVATE = 0x0000;
/**
+ * @deprecated Creating world-readable files is very dangerous, and likely
+ * to cause security holes in applications. It is strongly discouraged;
+ * instead, applications should use more formal mechanism for interactions
+ * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
+ * {@link android.app.Service}. There are no guarantees that this
+ * access mode will remain on a file, such as when it goes through a
+ * backup and restore.
* File creation mode: allow all other applications to have read access
* to the created file.
- *
- * Note: Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, world-readable files created within the
- * application's home directory will not be accessible to other applications.
- *
- * @deprecated Creating world-readable files is very dangerous, and likely
- * to cause security holes in applications. It is strongly discouraged;
- * instead, applications should use more formal mechanism for interactions
- * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
- * {@link android.app.Service}. There are no guarantees that this
- * access mode will remain on a file, such as when it goes through a
- * backup and restore.
* @see #MODE_PRIVATE
* @see #MODE_WORLD_WRITEABLE
*/
@Deprecated
public static final int MODE_WORLD_READABLE = 0x0001;
/**
+ * @deprecated Creating world-writable files is very dangerous, and likely
+ * to cause security holes in applications. It is strongly discouraged;
+ * instead, applications should use more formal mechanism for interactions
+ * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
+ * {@link android.app.Service}. There are no guarantees that this
+ * access mode will remain on a file, such as when it goes through a
+ * backup and restore.
* File creation mode: allow all other applications to have write access
* to the created file.
- *
- * Note: Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, world-writable files created within the
- * application's home directory will not be accessible to other applications.
- *
- * @deprecated Creating world-writable files is very dangerous, and likely
- * to cause security holes in applications. It is strongly discouraged;
- * instead, applications should use more formal mechanism for interactions
- * such as {@link ContentProvider}, {@link BroadcastReceiver}, and
- * {@link android.app.Service}. There are no guarantees that this
- * access mode will remain on a file, such as when it goes through a
- * backup and restore.
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
*/
@@ -515,22 +501,18 @@ public abstract class Context {
throws FileNotFoundException;
/**
- * Open a file associated with this Context's application package
+ * Open a private file associated with this Context's application package
* for writing. Creates the file if it doesn't already exist.
*
- * Note: Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, files created with {@code mode}
- * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be
- * accessible to other applications.
- *
- * @param name The name of the file to open; can not contain path separators.
+ * @param name The name of the file to open; can not contain path
+ * separators.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_APPEND} to append to an existing file,
- * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control
- * permissions.
+ * default operation, {@link #MODE_APPEND} to append to an existing file,
+ * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control
+ * permissions.
+ *
* @return FileOutputStream Resulting output stream.
+ *
* @see #MODE_APPEND
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
@@ -756,19 +738,14 @@ public abstract class Context {
* application; you can only set the mode of the entire directory, not
* of individual files.
*
- * Note: Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, world-readable / world-writable directories
- * created using this method will not be accessible to other applications.
- *
* @param name Name of the directory to retrieve. This is a directory
- * that is created as part of your application data.
+ * that is created as part of your application data.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_WORLD_READABLE} and
- * {@link #MODE_WORLD_WRITEABLE} to control permissions.
+ * default operation, {@link #MODE_WORLD_READABLE} and
+ * {@link #MODE_WORLD_WRITEABLE} to control permissions.
+ *
* @return Returns a File object for the requested directory. The directory
- * will have been created if it does not already exist.
+ * will have been created if it does not already exist.
*
* @see #openFileOutput(String, int)
*/
@@ -778,13 +755,6 @@ public abstract class Context {
* Open a new private SQLiteDatabase associated with this Context's
* application package. Create the database file if it doesn't exist.
*
- * Note: Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, {@code SQLiteDatabase}s created with {@code mode}
- * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be
- * accessible to other applications.
- *
* @param name The name (unique in the application package) of the database.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
* default operation, {@link #MODE_WORLD_READABLE}
@@ -792,8 +762,10 @@ public abstract class Context {
* Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
* @param factory An optional factory class that is called to instantiate a
* cursor when query is called.
+ *
* @return The contents of a newly created database with the given name.
* @throws android.database.sqlite.SQLiteException if the database file could not be opened.
+ *
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
@@ -810,13 +782,6 @@ public abstract class Context {
* Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
* used to handle corruption when sqlite reports database corruption.
*
- * Note: Applications with {@code targetSdkVersion}
- * {@link android.os.Build.VERSION_CODES#K} or greater have home directories
- * with {@code 0700} permissions. Because an application's home directory
- * is no longer world-accessible, {@code SQLiteDatabase}s created with {@code mode}
- * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be
- * accessible to other applications.
- *
* @param name The name (unique in the application package) of the database.
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
* default operation, {@link #MODE_WORLD_READABLE}
@@ -825,9 +790,10 @@ public abstract class Context {
* @param factory An optional factory class that is called to instantiate a
* cursor when query is called.
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
- * corruption. if null, {@link android.database.DefaultDatabaseErrorHandler} is assumed.
+ * corruption. if null, {@link android.database.DefaultDatabaseErrorHandler} is assumed.
* @return The contents of a newly created database with the given name.
* @throws android.database.sqlite.SQLiteException if the database file could not be opened.
+ *
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index d69d2a658e180..a7f39d5ef1ac5 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -431,17 +431,6 @@ public class Build {
*
*/
public static final int JELLY_BEAN_MR1 = 17;
-
- /**
- * Android X.X: "K". Just "K"
- *
- * Applications targeting this or a later release will get these
- * new changes in behavior:
- *
- * - Application home directory permissions are now {@code 0700}.
- *
- */
- public static final int K = CUR_DEVELOPMENT;
}
/** The type of build, like "user" or "eng". */
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index e96820f266977..02a2c1b0c7110 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -188,12 +188,7 @@ public final class Installer {
}
}
- /**
- * @param restrictHomeDir if {@code true}, installd will create the application's
- * home directory with {@code 0700} permissions. If false, {@code 0751} will
- * be used instead.
- */
- public int install(String name, int uid, int gid, boolean restrictHomeDir) {
+ public int install(String name, int uid, int gid) {
StringBuilder builder = new StringBuilder("install");
builder.append(' ');
builder.append(name);
@@ -201,8 +196,6 @@ public final class Installer {
builder.append(uid);
builder.append(' ');
builder.append(gid);
- builder.append(' ');
- builder.append(restrictHomeDir);
return execute(builder.toString());
}
@@ -270,12 +263,7 @@ public final class Installer {
return execute(builder.toString());
}
- /**
- * @param restrictHomeDir if {@code true}, installd will create the application's
- * home directory with {@code 0700} permissions. If false, {@code 0751} will
- * be used instead.
- */
- public int createUserData(String name, int uid, int userId, boolean restrictHomeDir) {
+ public int createUserData(String name, int uid, int userId) {
StringBuilder builder = new StringBuilder("mkuserdata");
builder.append(' ');
builder.append(name);
@@ -283,8 +271,6 @@ public final class Installer {
builder.append(uid);
builder.append(' ');
builder.append(userId);
- builder.append(' ');
- builder.append(restrictHomeDir);
return execute(builder.toString());
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index aa2b461216f7e..2238f17621f1c 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.removeInt;
+import static libcore.io.OsConstants.S_ISLNK;
import static libcore.io.OsConstants.S_IRWXU;
import static libcore.io.OsConstants.S_IRGRP;
import static libcore.io.OsConstants.S_IXGRP;
@@ -110,6 +111,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.Environment.UserEnvironment;
+import android.provider.Settings.Secure;
import android.security.SystemKeyStore;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -146,11 +148,13 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
import libcore.io.Libcore;
+import libcore.io.OsConstants;
import libcore.io.StructStat;
/**
@@ -3578,17 +3582,16 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private int createDataDirsLI(String packageName, int uid, int targetSdkVersion) {
+ private int createDataDirsLI(String packageName, int uid) {
int[] users = sUserManager.getUserIds();
- boolean restrictHomeDir = (targetSdkVersion >= Build.VERSION_CODES.K);
- int res = mInstaller.install(packageName, uid, uid, restrictHomeDir);
+ int res = mInstaller.install(packageName, uid, uid);
if (res < 0) {
return res;
}
for (int user : users) {
if (user != 0) {
res = mInstaller.createUserData(packageName,
- UserHandle.getUid(user, uid), user, restrictHomeDir);
+ UserHandle.getUid(user, uid), user);
if (res < 0) {
return res;
}
@@ -3982,8 +3985,7 @@ public class PackageManagerService extends IPackageManager.Stub {
recovered = true;
// And now re-install the app.
- ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.targetSdkVersion);
+ ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
if (ret == -1) {
// Ack should not happen!
msg = prefix + pkg.packageName
@@ -4028,9 +4030,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
Log.v(TAG, "Want this data dir: " + dataPath);
}
- // invoke installer to do the actual installation
- int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.targetSdkVersion);
+ //invoke installer to do the actual installation
+ int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
if (ret < 0) {
// Error from installer
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index f791a6e6e148d..06f11bc9a4dab 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -25,6 +25,7 @@ import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.XmlUtils;
+import com.android.server.IntentResolver;
import com.android.server.pm.PackageManagerService.DumpState;
import org.xmlpull.v1.XmlPullParser;
@@ -45,7 +46,6 @@ import android.content.pm.UserInfo;
import android.content.pm.PackageUserState;
import android.content.pm.VerifierDeviceIdentity;
import android.os.Binder;
-import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
@@ -2335,11 +2335,9 @@ final class Settings {
for (PackageSetting ps : mPackages.values()) {
// Only system apps are initially installed.
ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
- boolean restrictHomeDir = (ps.pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.K);
// Need to create a data directory for all apps under this user.
installer.createUserData(ps.name,
- UserHandle.getUid(userHandle, ps.appId), userHandle,
- restrictHomeDir);
+ UserHandle.getUid(userHandle, ps.appId), userHandle);
}
readDefaultPreferredAppsLPw(userHandle);
writePackageRestrictionsLPr(userHandle);
From f623b930d3661540f74370d3548ac0a056c3320b Mon Sep 17 00:00:00 2001
From: Nick Kralevich
Date: Wed, 9 Jan 2013 16:03:14 -0800
Subject: [PATCH 04/18] Add K api version.
Change-Id: I2b74e06f8bda8b23c5cc4280af4b18a5ad66a6c2
---
api/current.txt | 1 +
core/java/android/os/Build.java | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/api/current.txt b/api/current.txt
index cf24f1347e51c..e4d5fd1f188c1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15737,6 +15737,7 @@ package android.os {
field public static final int ICE_CREAM_SANDWICH_MR1 = 15; // 0xf
field public static final int JELLY_BEAN = 16; // 0x10
field public static final int JELLY_BEAN_MR1 = 17; // 0x11
+ field public static final int K = 10000; // 0x2710
}
public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index a7f39d5ef1ac5..52c89e868cf04 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -431,6 +431,11 @@ public class Build {
*
*/
public static final int JELLY_BEAN_MR1 = 17;
+
+ /**
+ * Android X.X: "K". Just "K"
+ */
+ public static final int K = CUR_DEVELOPMENT;
}
/** The type of build, like "user" or "eng". */
From 1efbb80d5e4ccc44419f823fb7bd3bd0e25b332d Mon Sep 17 00:00:00 2001
From: Laurent Tu
Date: Thu, 24 Jan 2013 15:10:24 -0800
Subject: [PATCH 05/18] Fix GpsLocationProvider.enable/disable/isEnabled
Fix the issue where GpsLocationProvider.isEnabled() returns true when it
is really false (and the other way around), when the handler hasn't
processed the enable/disable messages yet.
This can be systematically reproduced when the caller code is using the
same thread as the thread of the handler in GpsLocationProvider.
For example, this was happening in LocationManagerService.switchUser().
It would start by disabling all the providers (with
updateProviderListenersLocked()), then re-enable them in
updateProvidersLocked() only when isEnalbed()==false, which was in the
wrong state since the GpsLocationProvider.ENABLE message hadn't been
processed yet. As a result, the GpsLocationProvider was disabled upon
startup of the phone.
This is a slight problem for the enable() contract, which specifies that
getStatus() must be handled, getStatus() will be handled but might have
slighty not-up-to-date info in this case.
Bug: 8028017
Change-Id: Iff91a11cc150e9029a6db85b64a10a926e12b0ba
---
.../server/location/GpsLocationProvider.java | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 12c14bfa626c4..da150d9e6ca64 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -704,17 +704,17 @@ public class GpsLocationProvider implements LocationProviderInterface {
*/
@Override
public void enable() {
+ synchronized (mLock) {
+ if (mEnabled) return;
+ mEnabled = true;
+ }
+
sendMessage(ENABLE, 1, null);
}
private void handleEnable() {
if (DEBUG) Log.d(TAG, "handleEnable");
- synchronized (mLock) {
- if (mEnabled) return;
- mEnabled = true;
- }
-
boolean enabled = native_init();
if (enabled) {
@@ -740,17 +740,17 @@ public class GpsLocationProvider implements LocationProviderInterface {
*/
@Override
public void disable() {
+ synchronized (mLock) {
+ if (!mEnabled) return;
+ mEnabled = false;
+ }
+
sendMessage(ENABLE, 0, null);
}
private void handleDisable() {
if (DEBUG) Log.d(TAG, "handleDisable");
- synchronized (mLock) {
- if (!mEnabled) return;
- mEnabled = false;
- }
-
stopNavigating();
mAlarmManager.cancel(mWakeupIntent);
mAlarmManager.cancel(mTimeoutIntent);
From 8c5eb4a3d94241665663bc2b2aaaa8a15e3bafbd Mon Sep 17 00:00:00 2001
From: Jeff Sharkey
Date: Wed, 30 Jan 2013 10:58:40 -0800
Subject: [PATCH 06/18] Check text length when testing for newline.
Also add tests to verify.
Bug: 8102140
Change-Id: I7e5dbff53caeb50bfa0fb4ea5dce73e3c742986a
---
.../internal/util/FastXmlSerializer.java | 2 +-
.../internal/util/FastXmlSerializerTest.java | 47 +++++++++++++++++++
2 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 core/tests/coretests/src/com/android/internal/util/FastXmlSerializerTest.java
diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java
index 99eea151879fd..7a040801a9a50 100644
--- a/core/java/com/android/internal/util/FastXmlSerializer.java
+++ b/core/java/com/android/internal/util/FastXmlSerializer.java
@@ -390,7 +390,7 @@ public class FastXmlSerializer implements XmlSerializer {
}
escapeAndAppendString(text);
if (mIndent) {
- mLineStart = text.charAt(text.length()-1) == '\n';
+ mLineStart = text.length() > 0 && (text.charAt(text.length()-1) == '\n');
}
return this;
}
diff --git a/core/tests/coretests/src/com/android/internal/util/FastXmlSerializerTest.java b/core/tests/coretests/src/com/android/internal/util/FastXmlSerializerTest.java
new file mode 100644
index 0000000000000..be7116dffb899
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/util/FastXmlSerializerTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import junit.framework.TestCase;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Tests for {@link FastXmlSerializer}
+ */
+public class FastXmlSerializerTest extends TestCase {
+ public void testEmptyText() throws Exception {
+ final ByteArrayOutputStream stream = new ByteArrayOutputStream();
+
+ final XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(stream, "utf-8");
+ out.startDocument(null, true);
+ out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+
+ out.startTag(null, "string");
+ out.attribute(null, "name", "meow");
+ out.text("");
+ out.endTag(null, "string");
+
+ out.endDocument();
+
+ assertEquals("\n"
+ + "", stream.toString());
+ }
+}
From e28ecab813c5f15b117854fe4a3fac1f77d9b5b7 Mon Sep 17 00:00:00 2001
From: Mike Cleron
Date: Fri, 1 Feb 2013 18:36:41 +0000
Subject: [PATCH 07/18] Revert "Fixing backwards cmpatibility for enabling
explore by touch"
This reverts commit 0a9c7c144671f70f5f1af222050bd3ec6b11fe41
Change-Id: I8da530a6d0a57163522d5a63326e787a8d22ecbf
---
.../AccessibilityServiceInfo.java | 10 +-
core/java/android/provider/Settings.java | 1 +
core/res/res/values/strings.xml | 23 +-
.../providers/settings/DatabaseHelper.java | 18 +-
.../AccessibilityManagerService.java | 251 +++---------------
5 files changed, 57 insertions(+), 246 deletions(-)
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index d12a336b13b26..ef7186bb6a694 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -150,18 +150,10 @@ public class AccessibilityServiceInfo implements Parcelable {
* flag does not guarantee that the device will not be in touch exploration
* mode since there may be another enabled service that requested it.
*
- * For accessibility services targeting API version higher than
- * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set
- * this flag have to request the
+ * Clients that want to set this flag have to request the
* {@link android.Manifest.permission#CAN_REQUEST_TOUCH_EXPLORATION_MODE}
* permission or the flag will be ignored.
*
- *
- * Services targeting API version equal to or lower than
- * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e.
- * the first time they are run, if this flag is specified, a dialog is
- * shown to the user to confirm enabling explore by touch.
- *
*/
public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3d850cfb022dd..be21fb433f961 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3351,6 +3351,7 @@ public final class Settings {
*
* @hide
*/
+ @Deprecated
public static final String TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES =
"touch_exploration_granted_accessibility_services";
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index aae509edcdfc6..8f8f32de7c28d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -950,8 +950,8 @@
request enhanced web accessibility
Allows the hoder to request
- enabling of web accessibility enhancements. For example, installing scripts to make
- app content more accessible.
+ enabling of web accessibility enhancements. For example, installing scripts from
+ Google to make app content more accessible.
bind to a text service
@@ -2714,25 +2714,6 @@
Voice search
-
- Enable Explore by Touch?
-
-
- %1$s wants to enable Explore by Touch.
- When Explore by Touch is turned on, you can hear or see descriptions of what\'s under
- your finger or perform gestures to interact with the tablet.
-
-
- %1$s wants to enable Explore by Touch.
- When Explore by Touch is turned on, you can hear or see descriptions of what\'s under
- your finger or perform gestures to interact with the phone.
-
1 month ago
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index fc0ff559c5cc9..695c2aa708b85 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -71,7 +71,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 96;
+ private static final int DATABASE_VERSION = 97;
private Context mContext;
private int mUserHandle;
@@ -1536,6 +1536,22 @@ public class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 96;
}
+ if (upgradeVersion == 96) {
+ // Remove Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES
+ if (mUserHandle == UserHandle.USER_OWNER) {
+ db.beginTransaction();
+ try {
+ db.execSQL("DELETE FROM system WHERE name='"
+ + Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES
+ + "'");
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+ upgradeVersion = 97;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index bb040bffd6f2f..f4592f78cf64d 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -23,15 +23,12 @@ import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
-import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
@@ -70,7 +67,6 @@ import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
-import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityManager;
@@ -161,8 +157,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private Service mQueryBridge;
- private AlertDialog mEnableTouchExplorationDialog;
-
private AccessibilityInputFilter mInputFilter;
private boolean mHasInputFilter;
@@ -250,12 +244,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
persistComponentNamesToSettingLocked(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
state.mEnabledServices, userId);
- // Update the touch exploration granted services setting.
- state.mTouchExplorationGrantedServices.remove(comp);
- persistComponentNamesToSettingLocked(
- Settings.Secure.
- TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- state.mEnabledServices, userId);
return;
}
}
@@ -570,8 +558,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mIsDisplayMagnificationEnabled = false;
userState.mEnabledServices.clear();
userState.mEnabledServices.add(service);
- userState.mTouchExplorationGrantedServices.clear();
- userState.mTouchExplorationGrantedServices.add(service);
// Update the internal state.
performServiceManagementLocked(userState);
scheduleUpdateInputFilter(userState);
@@ -845,12 +831,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mEnabledServices);
}
- private void populateTouchExplorationGrantedAccessibilityServicesLocked(UserState userState) {
- populateComponentNamesFromSettingLocked(
- Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- userState.mUserId, userState.mTouchExplorationGrantedServices);
- }
-
/**
* Performs {@link AccessibilityService}s delayed notification. The delay is configurable
* and denotes the period after the last event before notifying the service.
@@ -1143,54 +1123,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
- private void showEnableTouchExplorationDialog(final Service service) {
- String label = service.mResolveInfo.loadLabel(
-
- mContext.getPackageManager()).toString();
- synchronized (mLock) {
- final UserState state = getCurrentUserStateLocked();
- if (state.mIsTouchExplorationEnabled) {
- return;
- }
- if (mEnableTouchExplorationDialog != null
- && mEnableTouchExplorationDialog.isShowing()) {
- return;
- }
- mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setPositiveButton(android.R.string.ok, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // The user allowed the service to toggle touch exploration.
- state.mTouchExplorationGrantedServices.add(service.mComponentName);
- persistComponentNamesToSettingLocked(
- Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
- state.mTouchExplorationGrantedServices, state.mUserId);
- // Enable touch exploration.
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
- service.mUserId);
- }
- })
- .setNegativeButton(android.R.string.cancel, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- })
- .setTitle(R.string.enable_explore_by_touch_warning_title)
- .setMessage(mContext.getString(
- R.string.enable_explore_by_touch_warning_message, label))
- .create();
- mEnableTouchExplorationDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
- |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
- mEnableTouchExplorationDialog.show();
- }
- }
-
private int getClientState(UserState userState) {
int clientState = 0;
if (userState.mIsAccessibilityEnabled) {
@@ -1206,16 +1138,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private void recreateInternalStateLocked(UserState userState) {
populateInstalledAccessibilityServiceLocked(userState);
populateEnabledAccessibilityServicesLocked(userState);
- populateTouchExplorationGrantedAccessibilityServicesLocked(userState);
- populatedEnhancedWebAccessibilityEnabledChangedLocked(userState);
handleTouchExplorationEnabledSettingChangedLocked(userState);
handleDisplayMagnificationEnabledSettingChangedLocked(userState);
handleAccessibilityEnabledSettingChangedLocked(userState);
- handleTouchExplorationGrantedAccessibilityServicesChangedLocked(userState);
performServiceManagementLocked(userState);
-
scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
@@ -1247,61 +1175,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
0, userState.mUserId) == 1;
}
- private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked(
- UserState userState) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
- final int serviceCount = userState.mServices.size();
- for (int i = 0; i < serviceCount; i++) {
- Service service = userState.mServices.get(i);
- tryEnableTouchExplorationLocked(service);
- }
- }
-
- private void populatedEnhancedWebAccessibilityEnabledChangedLocked(UserState userState) {
- userState.mIsEnhancedWebAccessibilityEnabled = Settings.Secure.getIntForUser(
- mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
- 0, userState.mUserId) == 1;
- }
-
private void tryEnableTouchExplorationLocked(Service service) {
- if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
+ if (!service.mRequestTouchExplorationMode || !service.canReceiveEventsLocked()) {
return;
}
UserState userState = getUserStateLocked(service.mUserId);
- if (userState.mIsTouchExplorationEnabled) {
- return;
- }
- // UI test automation service can always enable it.
- if (service.mIsAutomation) {
+ if (!userState.mIsTouchExplorationEnabled) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, service.mUserId);
- return;
- }
- if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
- <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- // Up to JB-MR1 we had a white list with services that can enable touch
- // exploration. When a service is first started we show a dialog to the
- // use to get a permission to white list the service.
- if (!userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
- if (mEnableTouchExplorationDialog == null
- || (mEnableTouchExplorationDialog != null
- && !mEnableTouchExplorationDialog.isShowing())) {
- showEnableTouchExplorationDialog(service);
- }
- } else {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, service.mUserId);
- }
- } else {
- // Starting in JB-MR2 we request a permission to allow a service to enable
- // touch exploration and do not care if the service is in the white list.
- if (mContext.getPackageManager().checkPermission(
- android.Manifest.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE,
- service.mComponentName.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, service.mUserId);
- }
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, userState.mUserId);
}
}
@@ -1310,53 +1191,25 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return;
}
UserState userState = getUserStateLocked(service.mUserId);
- if (!userState.mIsTouchExplorationEnabled) {
- return;
- }
- final int serviceCount = userState.mServices.size();
- for (int i = 0; i < serviceCount; i++) {
- Service other = userState.mServices.get(i);
- if (other != service) {
- if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
- <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- // Up to JB-MR1 we had a white list with services that can enable touch
- // exploration. When a service is first started we show a dialog to the
- // use to get a permission to white list the service.
- if (other.mRequestTouchExplorationMode &&
- userState.mTouchExplorationGrantedServices.contains(
- service.mComponentName)) {
- // A white-listed service wants touch exploration, do not disable.
- return;
- }
- } else {
- // Starting in JB-MR2 we request a permission to allow a service to enable
- // touch exploration and do not care if the service is in the white list.
- if (other.mRequestTouchExplorationMode && (service.mIsAutomation
- || mContext.getPackageManager().checkPermission(
- android.Manifest.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE,
- service.mComponentName.getPackageName())
- == PackageManager.PERMISSION_GRANTED)) {
- // A service with permission wants touch exploration, do not disable.
- return;
- }
+ if (userState.mIsTouchExplorationEnabled) {
+ final int serviceCount = userState.mServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ Service other = userState.mServices.get(i);
+ if (other != service && other.mRequestTouchExplorationMode) {
+ return;
}
}
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
}
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
}
private void tryEnableEnhancedWebAccessibilityLocked(Service service) {
- if (!service.canReceiveEventsLocked() || !service.mRequestEnhancedWebAccessibility ) {
+ if (!service.mRequestEnhancedWebAccessibility || !service.canReceiveEventsLocked()) {
return;
}
UserState userState = getUserStateLocked(service.mUserId);
- if (userState.mIsEnhancedWebAccessibilityEnabled) {
- return;
- }
- // Requested and can enabled, do it.
- if (service.mRequestEnhancedWebAccessibility
- && canEnabledEnhancedWebAccessibility(service)) {
+ if (!userState.mIsEnhancedWebAccessibilityEnabled) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 1, userState.mUserId);
}
@@ -1367,26 +1220,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return;
}
UserState userState = getUserStateLocked(service.mUserId);
- if (!userState.mIsEnhancedWebAccessibilityEnabled) {
- return;
- }
- final int serviceCount = userState.mServices.size();
- for (int i = 0; i < serviceCount; i++) {
- Service other = userState.mServices.get(i);
- if (other != service && other.mRequestEnhancedWebAccessibility
- && canEnabledEnhancedWebAccessibility(other)) {
- // One service requests the feature, do not disable.
- return;
+ if (userState.mIsEnhancedWebAccessibilityEnabled) {
+ final int serviceCount = userState.mServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ Service other = userState.mServices.get(i);
+ if (other != service && other.mRequestEnhancedWebAccessibility) {
+ return;
+ }
}
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0, userState.mUserId);
}
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0, service.mUserId);
- }
-
- private boolean canEnabledEnhancedWebAccessibility(Service service) {
- return (service.mIsAutomation || mContext.getPackageManager().checkPermission(
- android.Manifest.permission.CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY,
- service.mComponentName.getPackageName()) == PackageManager.PERMISSION_GRANTED);
}
@Override
@@ -1511,7 +1355,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} break;
case MSG_UPDATE_INPUT_FILTER: {
UserState userState = (UserState) msg.obj;
- updateInputFilter(userState);
+ updateInputFilter(userState);
} break;
}
}
@@ -1683,10 +1527,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS : 0;
if (mResolveInfo != null) {
- mRequestTouchExplorationMode = (info.flags
+ String packageName = mResolveInfo.serviceInfo.packageName;
+
+ if (mContext.getPackageManager().checkPermission(
+ android.Manifest.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE,
+ packageName) == PackageManager.PERMISSION_GRANTED) {
+ mRequestTouchExplorationMode = (info.flags
& AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
- mRequestEnhancedWebAccessibility = (info.flags
+ }
+
+ if (mContext.getPackageManager().checkPermission(
+ android.Manifest.permission.CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY,
+ packageName) == PackageManager.PERMISSION_GRANTED) {
+ mRequestEnhancedWebAccessibility = (info.flags
& AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0;
+ }
}
// If this service is up and running we may have to enable touch
@@ -2598,9 +2453,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public final Set mEnabledServices = new HashSet();
- public final Set mTouchExplorationGrantedServices =
- new HashSet();
-
public final SparseArray
mInteractionConnections =
new SparseArray();
@@ -2638,7 +2490,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
mEnabledServices.clear();
mEnabledServices.addAll(userState.mEnabledServices);
mTouchExplorationGrantedServices.clear();
- mTouchExplorationGrantedServices.addAll(userState.mTouchExplorationGrantedServices);
}
public void applyTo(UserState userState) {
@@ -2648,8 +2499,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mIsDisplayMagnificationEnabled = mIsDisplayMagnificationEnabled;
userState.mEnabledServices.clear();
userState.mEnabledServices.addAll(mEnabledServices);
- userState.mTouchExplorationGrantedServices.clear();
- userState.mTouchExplorationGrantedServices.addAll(mTouchExplorationGrantedServices);
}
public void clear() {
@@ -2677,12 +2526,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
- private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
- .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
-
- private final Uri mAccessibilityScriptInjectionUri = Settings.Secure
- .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION);
-
public AccessibilityContentObserver(Handler handler) {
super(handler);
}
@@ -2696,11 +2539,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
false, this, UserHandle.USER_ALL);
- contentResolver.registerContentObserver(
- mTouchExplorationGrantedAccessibilityServicesUri,
- false, this, UserHandle.USER_ALL);
- contentResolver.registerContentObserver(mAccessibilityScriptInjectionUri,
- false, this, UserHandle.USER_ALL);
}
@Override
@@ -2745,23 +2583,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
manageServicesLocked(userState);
}
}
- } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
- synchronized (mLock) {
- // We will update when the automation service dies.
- if (mUiAutomationService == null) {
- UserState userState = getCurrentUserStateLocked();
- populateTouchExplorationGrantedAccessibilityServicesLocked(userState);
- handleTouchExplorationGrantedAccessibilityServicesChangedLocked(userState);
- }
- }
- } else if (mAccessibilityScriptInjectionUri.equals(uri)) {
- synchronized (mLock) {
- // We will update when the automation service dies.
- if (mUiAutomationService == null) {
- UserState userState = getCurrentUserStateLocked();
- populatedEnhancedWebAccessibilityEnabledChangedLocked(userState);
- }
- }
}
}
}
From 9d44acae80f743b3de8c0ddf208aa5d526511a9b Mon Sep 17 00:00:00 2001
From: Svetoslav Ganov
Date: Fri, 1 Feb 2013 19:46:20 +0000
Subject: [PATCH 08/18] "Fixing backwards cmpatibility for enabling explore by
touch""
This reverts commit d1ed3cea37e4156eab14b7dc8207a520c9eab700
Change-Id: I622ef034526f8f006a5a233e72487b062020e4f6
---
.../AccessibilityServiceInfo.java | 10 +-
core/java/android/provider/Settings.java | 1 -
core/res/res/values/strings.xml | 23 +-
.../providers/settings/DatabaseHelper.java | 13 +-
.../AccessibilityManagerService.java | 253 +++++++++++++++---
5 files changed, 247 insertions(+), 53 deletions(-)
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index ef7186bb6a694..d12a336b13b26 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -150,10 +150,18 @@ public class AccessibilityServiceInfo implements Parcelable {
* flag does not guarantee that the device will not be in touch exploration
* mode since there may be another enabled service that requested it.
*
- * Clients that want to set this flag have to request the
+ * For accessibility services targeting API version higher than
+ * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set
+ * this flag have to request the
* {@link android.Manifest.permission#CAN_REQUEST_TOUCH_EXPLORATION_MODE}
* permission or the flag will be ignored.
*
+ *
+ * Services targeting API version equal to or lower than
+ * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e.
+ * the first time they are run, if this flag is specified, a dialog is
+ * shown to the user to confirm enabling explore by touch.
+ *
*/
public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index be21fb433f961..3d850cfb022dd 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3351,7 +3351,6 @@ public final class Settings {
*
* @hide
*/
- @Deprecated
public static final String TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES =
"touch_exploration_granted_accessibility_services";
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8f8f32de7c28d..aae509edcdfc6 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -950,8 +950,8 @@
request enhanced web accessibility
Allows the hoder to request
- enabling of web accessibility enhancements. For example, installing scripts from
- Google to make app content more accessible.
+ enabling of web accessibility enhancements. For example, installing scripts to make
+ app content more accessible.
bind to a text service
@@ -2714,6 +2714,25 @@
Voice search
+
+ Enable Explore by Touch?
+
+
+ %1$s wants to enable Explore by Touch.
+ When Explore by Touch is turned on, you can hear or see descriptions of what\'s under
+ your finger or perform gestures to interact with the tablet.
+
+
+ %1$s wants to enable Explore by Touch.
+ When Explore by Touch is turned on, you can hear or see descriptions of what\'s under
+ your finger or perform gestures to interact with the phone.
+
1 month ago
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 695c2aa708b85..16007c4cacdef 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1537,18 +1537,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
if (upgradeVersion == 96) {
- // Remove Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES
- if (mUserHandle == UserHandle.USER_OWNER) {
- db.beginTransaction();
- try {
- db.execSQL("DELETE FROM system WHERE name='"
- + Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES
- + "'");
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
- }
+ // NOP bump due to a reverted change that some people got on upgrade.
upgradeVersion = 97;
}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index f4592f78cf64d..bb040bffd6f2f 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -23,12 +23,15 @@ import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
@@ -67,6 +70,7 @@ import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
+import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityManager;
@@ -157,6 +161,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private Service mQueryBridge;
+ private AlertDialog mEnableTouchExplorationDialog;
+
private AccessibilityInputFilter mInputFilter;
private boolean mHasInputFilter;
@@ -244,6 +250,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
persistComponentNamesToSettingLocked(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
state.mEnabledServices, userId);
+ // Update the touch exploration granted services setting.
+ state.mTouchExplorationGrantedServices.remove(comp);
+ persistComponentNamesToSettingLocked(
+ Settings.Secure.
+ TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+ state.mEnabledServices, userId);
return;
}
}
@@ -558,6 +570,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mIsDisplayMagnificationEnabled = false;
userState.mEnabledServices.clear();
userState.mEnabledServices.add(service);
+ userState.mTouchExplorationGrantedServices.clear();
+ userState.mTouchExplorationGrantedServices.add(service);
// Update the internal state.
performServiceManagementLocked(userState);
scheduleUpdateInputFilter(userState);
@@ -831,6 +845,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mEnabledServices);
}
+ private void populateTouchExplorationGrantedAccessibilityServicesLocked(UserState userState) {
+ populateComponentNamesFromSettingLocked(
+ Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+ userState.mUserId, userState.mTouchExplorationGrantedServices);
+ }
+
/**
* Performs {@link AccessibilityService}s delayed notification. The delay is configurable
* and denotes the period after the last event before notifying the service.
@@ -1123,6 +1143,54 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
+ private void showEnableTouchExplorationDialog(final Service service) {
+ String label = service.mResolveInfo.loadLabel(
+
+ mContext.getPackageManager()).toString();
+ synchronized (mLock) {
+ final UserState state = getCurrentUserStateLocked();
+ if (state.mIsTouchExplorationEnabled) {
+ return;
+ }
+ if (mEnableTouchExplorationDialog != null
+ && mEnableTouchExplorationDialog.isShowing()) {
+ return;
+ }
+ mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setPositiveButton(android.R.string.ok, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // The user allowed the service to toggle touch exploration.
+ state.mTouchExplorationGrantedServices.add(service.mComponentName);
+ persistComponentNamesToSettingLocked(
+ Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+ state.mTouchExplorationGrantedServices, state.mUserId);
+ // Enable touch exploration.
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
+ service.mUserId);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ })
+ .setTitle(R.string.enable_explore_by_touch_warning_title)
+ .setMessage(mContext.getString(
+ R.string.enable_explore_by_touch_warning_message, label))
+ .create();
+ mEnableTouchExplorationDialog.getWindow().setType(
+ WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
+ |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
+ mEnableTouchExplorationDialog.show();
+ }
+ }
+
private int getClientState(UserState userState) {
int clientState = 0;
if (userState.mIsAccessibilityEnabled) {
@@ -1138,12 +1206,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private void recreateInternalStateLocked(UserState userState) {
populateInstalledAccessibilityServiceLocked(userState);
populateEnabledAccessibilityServicesLocked(userState);
+ populateTouchExplorationGrantedAccessibilityServicesLocked(userState);
+ populatedEnhancedWebAccessibilityEnabledChangedLocked(userState);
handleTouchExplorationEnabledSettingChangedLocked(userState);
handleDisplayMagnificationEnabledSettingChangedLocked(userState);
handleAccessibilityEnabledSettingChangedLocked(userState);
+ handleTouchExplorationGrantedAccessibilityServicesChangedLocked(userState);
performServiceManagementLocked(userState);
+
scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
@@ -1175,14 +1247,61 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
0, userState.mUserId) == 1;
}
+ private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked(
+ UserState userState) {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
+ final int serviceCount = userState.mServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ Service service = userState.mServices.get(i);
+ tryEnableTouchExplorationLocked(service);
+ }
+ }
+
+ private void populatedEnhancedWebAccessibilityEnabledChangedLocked(UserState userState) {
+ userState.mIsEnhancedWebAccessibilityEnabled = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
+ 0, userState.mUserId) == 1;
+ }
+
private void tryEnableTouchExplorationLocked(Service service) {
- if (!service.mRequestTouchExplorationMode || !service.canReceiveEventsLocked()) {
+ if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
return;
}
UserState userState = getUserStateLocked(service.mUserId);
- if (!userState.mIsTouchExplorationEnabled) {
+ if (userState.mIsTouchExplorationEnabled) {
+ return;
+ }
+ // UI test automation service can always enable it.
+ if (service.mIsAutomation) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, userState.mUserId);
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, service.mUserId);
+ return;
+ }
+ if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
+ <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ // Up to JB-MR1 we had a white list with services that can enable touch
+ // exploration. When a service is first started we show a dialog to the
+ // use to get a permission to white list the service.
+ if (!userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
+ if (mEnableTouchExplorationDialog == null
+ || (mEnableTouchExplorationDialog != null
+ && !mEnableTouchExplorationDialog.isShowing())) {
+ showEnableTouchExplorationDialog(service);
+ }
+ } else {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, service.mUserId);
+ }
+ } else {
+ // Starting in JB-MR2 we request a permission to allow a service to enable
+ // touch exploration and do not care if the service is in the white list.
+ if (mContext.getPackageManager().checkPermission(
+ android.Manifest.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE,
+ service.mComponentName.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, service.mUserId);
+ }
}
}
@@ -1191,25 +1310,53 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return;
}
UserState userState = getUserStateLocked(service.mUserId);
- if (userState.mIsTouchExplorationEnabled) {
- final int serviceCount = userState.mServices.size();
- for (int i = 0; i < serviceCount; i++) {
- Service other = userState.mServices.get(i);
- if (other != service && other.mRequestTouchExplorationMode) {
- return;
+ if (!userState.mIsTouchExplorationEnabled) {
+ return;
+ }
+ final int serviceCount = userState.mServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ Service other = userState.mServices.get(i);
+ if (other != service) {
+ if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
+ <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ // Up to JB-MR1 we had a white list with services that can enable touch
+ // exploration. When a service is first started we show a dialog to the
+ // use to get a permission to white list the service.
+ if (other.mRequestTouchExplorationMode &&
+ userState.mTouchExplorationGrantedServices.contains(
+ service.mComponentName)) {
+ // A white-listed service wants touch exploration, do not disable.
+ return;
+ }
+ } else {
+ // Starting in JB-MR2 we request a permission to allow a service to enable
+ // touch exploration and do not care if the service is in the white list.
+ if (other.mRequestTouchExplorationMode && (service.mIsAutomation
+ || mContext.getPackageManager().checkPermission(
+ android.Manifest.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE,
+ service.mComponentName.getPackageName())
+ == PackageManager.PERMISSION_GRANTED)) {
+ // A service with permission wants touch exploration, do not disable.
+ return;
+ }
}
}
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
}
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId);
}
private void tryEnableEnhancedWebAccessibilityLocked(Service service) {
- if (!service.mRequestEnhancedWebAccessibility || !service.canReceiveEventsLocked()) {
+ if (!service.canReceiveEventsLocked() || !service.mRequestEnhancedWebAccessibility ) {
return;
}
UserState userState = getUserStateLocked(service.mUserId);
- if (!userState.mIsEnhancedWebAccessibilityEnabled) {
+ if (userState.mIsEnhancedWebAccessibilityEnabled) {
+ return;
+ }
+ // Requested and can enabled, do it.
+ if (service.mRequestEnhancedWebAccessibility
+ && canEnabledEnhancedWebAccessibility(service)) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 1, userState.mUserId);
}
@@ -1220,17 +1367,26 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return;
}
UserState userState = getUserStateLocked(service.mUserId);
- if (userState.mIsEnhancedWebAccessibilityEnabled) {
- final int serviceCount = userState.mServices.size();
- for (int i = 0; i < serviceCount; i++) {
- Service other = userState.mServices.get(i);
- if (other != service && other.mRequestEnhancedWebAccessibility) {
- return;
- }
- }
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0, userState.mUserId);
+ if (!userState.mIsEnhancedWebAccessibilityEnabled) {
+ return;
}
+ final int serviceCount = userState.mServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ Service other = userState.mServices.get(i);
+ if (other != service && other.mRequestEnhancedWebAccessibility
+ && canEnabledEnhancedWebAccessibility(other)) {
+ // One service requests the feature, do not disable.
+ return;
+ }
+ }
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0, service.mUserId);
+ }
+
+ private boolean canEnabledEnhancedWebAccessibility(Service service) {
+ return (service.mIsAutomation || mContext.getPackageManager().checkPermission(
+ android.Manifest.permission.CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY,
+ service.mComponentName.getPackageName()) == PackageManager.PERMISSION_GRANTED);
}
@Override
@@ -1355,7 +1511,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} break;
case MSG_UPDATE_INPUT_FILTER: {
UserState userState = (UserState) msg.obj;
- updateInputFilter(userState);
+ updateInputFilter(userState);
} break;
}
}
@@ -1527,21 +1683,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS : 0;
if (mResolveInfo != null) {
- String packageName = mResolveInfo.serviceInfo.packageName;
-
- if (mContext.getPackageManager().checkPermission(
- android.Manifest.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE,
- packageName) == PackageManager.PERMISSION_GRANTED) {
- mRequestTouchExplorationMode = (info.flags
+ mRequestTouchExplorationMode = (info.flags
& AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
- }
-
- if (mContext.getPackageManager().checkPermission(
- android.Manifest.permission.CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY,
- packageName) == PackageManager.PERMISSION_GRANTED) {
- mRequestEnhancedWebAccessibility = (info.flags
+ mRequestEnhancedWebAccessibility = (info.flags
& AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0;
- }
}
// If this service is up and running we may have to enable touch
@@ -2453,6 +2598,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public final Set mEnabledServices = new HashSet();
+ public final Set mTouchExplorationGrantedServices =
+ new HashSet();
+
public final SparseArray
mInteractionConnections =
new SparseArray();
@@ -2490,6 +2638,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
mEnabledServices.clear();
mEnabledServices.addAll(userState.mEnabledServices);
mTouchExplorationGrantedServices.clear();
+ mTouchExplorationGrantedServices.addAll(userState.mTouchExplorationGrantedServices);
}
public void applyTo(UserState userState) {
@@ -2499,6 +2648,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mIsDisplayMagnificationEnabled = mIsDisplayMagnificationEnabled;
userState.mEnabledServices.clear();
userState.mEnabledServices.addAll(mEnabledServices);
+ userState.mTouchExplorationGrantedServices.clear();
+ userState.mTouchExplorationGrantedServices.addAll(mTouchExplorationGrantedServices);
}
public void clear() {
@@ -2526,6 +2677,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+ private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
+ .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
+
+ private final Uri mAccessibilityScriptInjectionUri = Settings.Secure
+ .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION);
+
public AccessibilityContentObserver(Handler handler) {
super(handler);
}
@@ -2539,6 +2696,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
false, this, UserHandle.USER_ALL);
+ contentResolver.registerContentObserver(
+ mTouchExplorationGrantedAccessibilityServicesUri,
+ false, this, UserHandle.USER_ALL);
+ contentResolver.registerContentObserver(mAccessibilityScriptInjectionUri,
+ false, this, UserHandle.USER_ALL);
}
@Override
@@ -2583,6 +2745,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
manageServicesLocked(userState);
}
}
+ } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
+ synchronized (mLock) {
+ // We will update when the automation service dies.
+ if (mUiAutomationService == null) {
+ UserState userState = getCurrentUserStateLocked();
+ populateTouchExplorationGrantedAccessibilityServicesLocked(userState);
+ handleTouchExplorationGrantedAccessibilityServicesChangedLocked(userState);
+ }
+ }
+ } else if (mAccessibilityScriptInjectionUri.equals(uri)) {
+ synchronized (mLock) {
+ // We will update when the automation service dies.
+ if (mUiAutomationService == null) {
+ UserState userState = getCurrentUserStateLocked();
+ populatedEnhancedWebAccessibilityEnabledChangedLocked(userState);
+ }
+ }
}
}
}
From fb6239bf71b2b1f7f437cec8b9b4f280da515492 Mon Sep 17 00:00:00 2001
From: Romain Guy
Date: Wed, 6 Feb 2013 16:51:04 -0800
Subject: [PATCH 09/18] Add a RenderBuffer object to store stencil buffers. Bug
#7146141
This change is needed to add a render buffer cache to avoid
creating and destroying stencil buffers on every frame.
This change also allows the renderer to use a 1 bit or 4 bit
stencil buffer whenever possible.
Finally this change fixes a bug introduced by a previous CL
which causes the stencil buffer to not be updated in certain
conditions. The fix relies on a new optional parameter in
drawColorRects() that can be used to avoid performing a
quickReject on rectangles generated by the clip region.
Change-Id: I2f55a8e807009887b276a83cde9f53fd5c01199f
---
libs/hwui/Android.mk | 1 +
libs/hwui/Caches.cpp | 10 +-
libs/hwui/Caches.h | 6 +-
libs/hwui/Debug.h | 3 +
libs/hwui/Extensions.cpp | 87 ++++++++++++++++++
libs/hwui/Extensions.h | 61 +++----------
libs/hwui/GradientCache.cpp | 2 +-
libs/hwui/Layer.cpp | 10 +-
libs/hwui/Layer.h | 56 ++++++------
libs/hwui/LayerRenderer.cpp | 2 +-
libs/hwui/OpenGLRenderer.cpp | 28 +++---
libs/hwui/OpenGLRenderer.h | 5 +-
libs/hwui/RenderBuffer.h | 171 +++++++++++++++++++++++++++++++++++
libs/hwui/Snapshot.cpp | 3 +
libs/hwui/Stencil.cpp | 29 +++++-
libs/hwui/Stencil.h | 7 ++
libs/hwui/TextureCache.cpp | 2 +-
17 files changed, 369 insertions(+), 114 deletions(-)
create mode 100644 libs/hwui/Extensions.cpp
create mode 100644 libs/hwui/RenderBuffer.h
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 881d160d02a67..2111a56578c2f 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -14,6 +14,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
DisplayListLogBuffer.cpp \
DisplayListRenderer.cpp \
Dither.cpp \
+ Extensions.cpp \
FboCache.cpp \
GradientCache.cpp \
Layer.cpp \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 1a86b3a4b32b3..492bb7d171f54 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -47,7 +47,7 @@ namespace uirenderer {
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-Caches::Caches(): Singleton(), mInitialized(false) {
+Caches::Caches(): Singleton(), mExtensions(Extensions::getInstance()), mInitialized(false) {
init();
initFont();
initExtensions();
@@ -100,7 +100,7 @@ void Caches::initFont() {
}
void Caches::initExtensions() {
- if (extensions.hasDebugMarker()) {
+ if (mExtensions.hasDebugMarker()) {
eventMark = glInsertEventMarkerEXT;
startMark = glPushGroupMarkerEXT;
endMark = glPopGroupMarkerEXT;
@@ -110,7 +110,7 @@ void Caches::initExtensions() {
endMark = endMarkNull;
}
- if (extensions.hasDebugLabel()) {
+ if (mExtensions.hasDebugLabel()) {
setLabel = glLabelObjectEXT;
getLabel = glGetObjectLabelEXT;
} else {
@@ -470,13 +470,13 @@ void Caches::resetScissor() {
///////////////////////////////////////////////////////////////////////////////
void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool discard) {
- if (extensions.hasTiledRendering() && !debugOverdraw) {
+ if (mExtensions.hasTiledRendering() && !debugOverdraw) {
glStartTilingQCOM(x, y, width, height, (discard ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM));
}
}
void Caches::endTiling() {
- if (extensions.hasTiledRendering() && !debugOverdraw) {
+ if (mExtensions.hasTiledRendering() && !debugOverdraw) {
glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM);
}
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index d73ac1e84aace..0fa54fb9f2f2e 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -25,7 +25,6 @@
#include
-#include "Extensions.h"
#include "FontRenderer.h"
#include "GammaFontRenderer.h"
#include "TextureCache.h"
@@ -243,9 +242,6 @@ public:
// VBO to draw with
GLuint meshBuffer;
- // GL extensions
- Extensions extensions;
-
// Misc
GLint maxTextureSize;
bool debugLayersUpdates;
@@ -311,6 +307,8 @@ private:
GLint mScissorWidth;
GLint mScissorHeight;
+ Extensions& mExtensions;
+
// Used to render layers
TextureVertex* mRegionMesh;
GLuint mRegionMeshIndices;
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index dfc4e25cc085c..5f8baacb710cf 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -44,6 +44,9 @@
// Turn on to display info about layers
#define DEBUG_LAYERS 0
+// Turn on to make stencil operations easier to debug
+#define DEBUG_STENCIL 0
+
// Turn on to display debug info about 9patch objects
#define DEBUG_PATCHES 0
// Turn on to "explode" 9patch objects
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
new file mode 100644
index 0000000000000..edc90fbc80f06
--- /dev/null
+++ b/libs/hwui/Extensions.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Debug.h"
+#include "Extensions.h"
+
+namespace android {
+
+using namespace uirenderer;
+ANDROID_SINGLETON_STATIC_INSTANCE(Extensions);
+
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Debug
+#if DEBUG_EXTENSIONS
+ #define EXT_LOGD(...) ALOGD(__VA_ARGS__)
+#else
+ #define EXT_LOGD(...)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Constructors
+///////////////////////////////////////////////////////////////////////////////
+
+Extensions::Extensions(): Singleton() {
+ const char* buffer = (const char*) glGetString(GL_EXTENSIONS);
+ const char* current = buffer;
+ const char* head = current;
+ EXT_LOGD("Available GL extensions:");
+ do {
+ head = strchr(current, ' ');
+ String8 s(current, head ? head - current : strlen(current));
+ if (s.length()) {
+ mExtensionList.add(s);
+ EXT_LOGD(" %s", s.string());
+ }
+ current = head + 1;
+ } while (head);
+
+ mHasNPot = hasExtension("GL_OES_texture_npot");
+ mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch");
+ mHasDiscardFramebuffer = hasExtension("GL_EXT_discard_framebuffer");
+ mHasDebugMarker = hasExtension("GL_EXT_debug_marker");
+ mHasDebugLabel = hasExtension("GL_EXT_debug_label");
+ mHasTiledRendering = hasExtension("GL_QCOM_tiled_rendering");
+ mHas1BitStencil = hasExtension("GL_OES_stencil1");
+ mHas4BitStencil = hasExtension("GL_OES_stencil4");
+
+ mExtensions = strdup(buffer);
+}
+
+Extensions::~Extensions() {
+ free(mExtensions);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Methods
+///////////////////////////////////////////////////////////////////////////////
+
+bool Extensions::hasExtension(const char* extension) const {
+ const String8 s(extension);
+ return mExtensionList.indexOf(s) >= 0;
+}
+
+void Extensions::dump() const {
+ ALOGD("Supported extensions:\n%s", mExtensions);
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index bdaa3cc06aa87..a069a6aae6914 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -17,62 +17,24 @@
#ifndef ANDROID_HWUI_EXTENSIONS_H
#define ANDROID_HWUI_EXTENSIONS_H
+#include
#include
#include
#include
#include
-#include "Debug.h"
-
namespace android {
namespace uirenderer {
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-// Debug
-#if DEBUG_EXTENSIONS
- #define EXT_LOGD(...) ALOGD(__VA_ARGS__)
-#else
- #define EXT_LOGD(...)
-#endif
-
///////////////////////////////////////////////////////////////////////////////
// Classes
///////////////////////////////////////////////////////////////////////////////
-class Extensions {
+class Extensions: public Singleton {
public:
- Extensions() {
- const char* buffer = (const char*) glGetString(GL_EXTENSIONS);
- const char* current = buffer;
- const char* head = current;
- EXT_LOGD("Available GL extensions:");
- do {
- head = strchr(current, ' ');
- String8 s(current, head ? head - current : strlen(current));
- if (s.length()) {
- mExtensionList.add(s);
- EXT_LOGD(" %s", s.string());
- }
- current = head + 1;
- } while (head);
-
- mHasNPot = hasExtension("GL_OES_texture_npot");
- mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch");
- mHasDiscardFramebuffer = hasExtension("GL_EXT_discard_framebuffer");
- mHasDebugMarker = hasExtension("GL_EXT_debug_marker");
- mHasDebugLabel = hasExtension("GL_EXT_debug_label");
- mHasTiledRendering = hasExtension("GL_QCOM_tiled_rendering");
-
- mExtensions = strdup(buffer);
- }
-
- ~Extensions() {
- free(mExtensions);
- }
+ Extensions();
+ ~Extensions();
inline bool hasNPot() const { return mHasNPot; }
inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; }
@@ -80,17 +42,16 @@ public:
inline bool hasDebugMarker() const { return mHasDebugMarker; }
inline bool hasDebugLabel() const { return mHasDebugLabel; }
inline bool hasTiledRendering() const { return mHasTiledRendering; }
+ inline bool has1BitStencil() const { return mHas1BitStencil; }
+ inline bool has4BitStencil() const { return mHas4BitStencil; }
- bool hasExtension(const char* extension) const {
- const String8 s(extension);
- return mExtensionList.indexOf(s) >= 0;
- }
+ bool hasExtension(const char* extension) const;
- void dump() {
- ALOGD("Supported extensions:\n%s", mExtensions);
- }
+ void dump() const;
private:
+ friend class Singleton;
+
SortedVector mExtensionList;
char* mExtensions;
@@ -101,6 +62,8 @@ private:
bool mHasDebugMarker;
bool mHasDebugLabel;
bool mHasTiledRendering;
+ bool mHas1BitStencil;
+ bool mHas4BitStencil;
}; // class Extensions
}; // namespace uirenderer
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 154c0ecce5edf..78f9cf5f7f196 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -152,7 +152,7 @@ void GradientCache::getGradientInfo(const uint32_t* colors, const int count,
GradientInfo& info) {
uint32_t width = 256 * (count - 1);
- if (!Caches::getInstance().extensions.hasNPot()) {
+ if (!Extensions::getInstance().hasNPot()) {
width = 1 << (31 - __builtin_clz(width));
}
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 79dbfb0fc3a5a..9247b1da3df27 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -41,7 +41,7 @@ Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
renderer = NULL;
displayList = NULL;
fbo = 0;
- stencil = 0;
+ stencil = NULL;
debugDrawUpdate = false;
Caches::getInstance().resourceCache.incrementRefcount(this);
}
@@ -87,8 +87,8 @@ bool Layer::resize(const uint32_t width, const uint32_t height) {
}
if (stencil) {
- bindStencilRenderBuffer();
- allocateStencilRenderBuffer();
+ stencil->bind();
+ stencil->resize(desiredWidth, desiredHeight);
if (glGetError() != GL_NO_ERROR) {
setSize(oldWidth, oldHeight);
@@ -108,8 +108,8 @@ void Layer::removeFbo(bool flush) {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
- glDeleteRenderbuffers(1, &stencil);
- stencil = 0;
+ delete stencil;
+ stencil = NULL;
}
if (fbo) {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index a580d899458b3..ccf1da5539aaa 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -27,6 +27,7 @@
#include
#include "Rect.h"
+#include "RenderBuffer.h"
#include "SkiaColorFilter.h"
#include "Texture.h"
#include "Vertex.h"
@@ -87,11 +88,11 @@ struct Layer {
deferredUpdateScheduled = true;
}
- inline uint32_t getWidth() {
+ inline uint32_t getWidth() const {
return texture.width;
}
- inline uint32_t getHeight() {
+ inline uint32_t getHeight() const {
return texture.height;
}
@@ -117,7 +118,7 @@ struct Layer {
texture.blend = blend;
}
- inline bool isBlend() {
+ inline bool isBlend() const {
return texture.blend;
}
@@ -130,11 +131,11 @@ struct Layer {
this->mode = mode;
}
- inline int getAlpha() {
+ inline int getAlpha() const {
return alpha;
}
- inline SkXfermode::Mode getMode() {
+ inline SkXfermode::Mode getMode() const {
return mode;
}
@@ -142,7 +143,7 @@ struct Layer {
this->empty = empty;
}
- inline bool isEmpty() {
+ inline bool isEmpty() const {
return empty;
}
@@ -150,23 +151,29 @@ struct Layer {
this->fbo = fbo;
}
- inline GLuint getFbo() {
+ inline GLuint getFbo() const {
return fbo;
}
- inline void setStencilRenderBuffer(GLuint renderBuffer) {
- this->stencil = renderBuffer;
+ inline void setStencilRenderBuffer(RenderBuffer* renderBuffer) {
+ if (RenderBuffer::isStencilBuffer(renderBuffer->getFormat())) {
+ this->stencil = renderBuffer;
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, stencil->getName());
+ } else {
+ ALOGE("The specified render buffer is not a stencil buffer");
+ }
}
- inline GLuint getStencilRenderBuffer() {
+ inline RenderBuffer* getStencilRenderBuffer() const {
return stencil;
}
- inline GLuint getTexture() {
+ inline GLuint getTexture() const {
return texture.id;
}
- inline GLenum getRenderTarget() {
+ inline GLenum getRenderTarget() const {
return renderTarget;
}
@@ -182,7 +189,7 @@ struct Layer {
texture.setFilter(filter, bindTexture, force, renderTarget);
}
- inline bool isCacheable() {
+ inline bool isCacheable() const {
return cacheable;
}
@@ -190,7 +197,7 @@ struct Layer {
this->cacheable = cacheable;
}
- inline bool isDirty() {
+ inline bool isDirty() const {
return dirty;
}
@@ -198,7 +205,7 @@ struct Layer {
this->dirty = dirty;
}
- inline bool isTextureLayer() {
+ inline bool isTextureLayer() const {
return textureLayer;
}
@@ -206,21 +213,21 @@ struct Layer {
this->textureLayer = textureLayer;
}
- inline SkiaColorFilter* getColorFilter() {
+ inline SkiaColorFilter* getColorFilter() const {
return colorFilter;
}
ANDROID_API void setColorFilter(SkiaColorFilter* filter);
- inline void bindTexture() {
+ inline void bindTexture() const {
if (texture.id) {
glBindTexture(renderTarget, texture.id);
}
}
- inline void bindStencilRenderBuffer() {
+ inline void bindStencilRenderBuffer() const {
if (stencil) {
- glBindRenderbuffer(GL_RENDERBUFFER, stencil);
+ stencil->bind();
}
}
@@ -256,12 +263,6 @@ struct Layer {
}
}
- inline void allocateStencilRenderBuffer() {
- if (stencil) {
- glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWidth(), getHeight());
- }
- }
-
inline mat4& getTexTransform() {
return texTransform;
}
@@ -318,10 +319,9 @@ private:
GLuint fbo;
/**
- * Name of the render buffer used as the stencil buffer. If the
- * name is 0, this layer does not have a stencil buffer.
+ * The render buffer used as the stencil buffer.
*/
- GLuint stencil;
+ RenderBuffer* stencil;
/**
* Indicates whether this layer has been used already.
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index c8a8ed441c43d..bc660cd8c2a93 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -351,7 +351,7 @@ void LayerRenderer::flushLayer(Layer* layer) {
if (layer && fbo) {
// If possible, discard any enqueud operations on deferred
// rendering architectures
- if (Caches::getInstance().extensions.hasDiscardFramebuffer()) {
+ if (Extensions::getInstance().hasDiscardFramebuffer()) {
GLuint previousFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1a760a84b8f34..708ff554d0704 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -109,7 +109,8 @@ static const Blender gBlendsSwap[] = {
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-OpenGLRenderer::OpenGLRenderer(): mCaches(Caches::getInstance()) {
+OpenGLRenderer::OpenGLRenderer():
+ mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
mShader = NULL;
mColorFilter = NULL;
mHasShadow = false;
@@ -216,7 +217,7 @@ void OpenGLRenderer::discardFramebuffer(float left, float top, float right, floa
// If we know that we are going to redraw the entire framebuffer,
// perform a discard to let the driver know we don't need to preserve
// the back buffer for this frame.
- if (mCaches.extensions.hasDiscardFramebuffer() &&
+ if (mExtensions.hasDiscardFramebuffer() &&
left <= 0.0f && top <= 0.0f && right >= mWidth && bottom >= mHeight) {
const bool isFbo = getTargetFbo() == 0;
const GLenum attachments[] = {
@@ -1119,7 +1120,7 @@ void OpenGLRenderer::drawRegionRects(const SkRegion& region, int color,
it.next();
}
- drawColorRects(rects.array(), count, color, mode, true, dirty);
+ drawColorRects(rects.array(), count, color, mode, true, dirty, false);
}
void OpenGLRenderer::dirtyLayer(const float left, const float top,
@@ -1269,15 +1270,12 @@ void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) {
// attach the new render buffer then turn tiling back on
endTiling();
- // TODO: See Layer::removeFbo(). The stencil renderbuffer should be cached
- GLuint buffer;
- glGenRenderbuffers(1, &buffer);
+ RenderBuffer* buffer = new RenderBuffer(
+ Stencil::getSmallestStencilFormat(), layer->getWidth(), layer->getHeight());
+ buffer->bind();
+ buffer->allocate();
layer->setStencilRenderBuffer(buffer);
- layer->bindStencilRenderBuffer();
- layer->allocateStencilRenderBuffer();
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer);
startTiling(layer->clipRect, layer->layer.getHeight());
}
@@ -1521,13 +1519,13 @@ void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
void OpenGLRenderer::setupDrawShader() {
if (mShader) {
- mShader->describe(mDescription, mCaches.extensions);
+ mShader->describe(mDescription, mExtensions);
}
}
void OpenGLRenderer::setupDrawColorFilter() {
if (mColorFilter) {
- mColorFilter->describe(mDescription, mCaches.extensions);
+ mColorFilter->describe(mDescription, mExtensions);
}
}
@@ -2916,7 +2914,7 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
}
status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color,
- SkXfermode::Mode mode, bool ignoreTransform, bool dirty) {
+ SkXfermode::Mode mode, bool ignoreTransform, bool dirty, bool clip) {
float left = FLT_MAX;
float top = FLT_MAX;
@@ -2950,7 +2948,7 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color
}
}
- if (count == 0 || quickReject(left, top, right, bottom)) {
+ if (count == 0 || (clip && quickReject(left, top, right, bottom))) {
return DrawGlInfo::kStatusDone;
}
@@ -3095,7 +3093,7 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
// If the blend mode cannot be implemented using shaders, fall
// back to the default SrcOver blend mode instead
if (CC_UNLIKELY(mode > SkXfermode::kScreen_Mode)) {
- if (CC_UNLIKELY(mCaches.extensions.hasFramebufferFetch())) {
+ if (CC_UNLIKELY(mExtensions.hasFramebufferFetch())) {
description.framebufferMode = mode;
description.swapSrcDst = swapSrcDst;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index ee205a4a7225f..0ad81c1f64e6a 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -567,9 +567,11 @@ private:
* @param mode The Skia xfermode to use
* @param ignoreTransform True if the current transform should be ignored
* @param dirty True if calling this method should dirty the current layer
+ * @param clip True if the rects should be clipped, false otherwise
*/
status_t drawColorRects(const float* rects, int count, int color,
- SkXfermode::Mode mode, bool ignoreTransform = false, bool dirty = true);
+ SkXfermode::Mode mode, bool ignoreTransform = false,
+ bool dirty = true, bool clip = true);
/**
* Draws the shape represented by the specified path texture.
@@ -888,6 +890,7 @@ private:
// Various caches
Caches& mCaches;
+ Extensions& mExtensions;
// List of rectangles to clear after saveLayer() is invoked
Vector mLayers;
diff --git a/libs/hwui/RenderBuffer.h b/libs/hwui/RenderBuffer.h
new file mode 100644
index 0000000000000..927f2659abd02
--- /dev/null
+++ b/libs/hwui/RenderBuffer.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_RENDER_BUFFER_H
+#define ANDROID_HWUI_RENDER_BUFFER_H
+
+#include
+#include
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * Represents an OpenGL render buffer. Render buffers are attached
+ * to layers to perform stencil work.
+ */
+struct RenderBuffer {
+ /**
+ * Creates a new render buffer in the specified format and dimensions.
+ * The format must be one of the formats allowed by glRenderbufferStorage().
+ */
+ RenderBuffer(GLenum format, uint32_t width, uint32_t height):
+ mFormat(format), mWidth(width), mHeight(height), mAllocated(false) {
+
+ glGenRenderbuffers(1, &mName);
+ }
+
+ ~RenderBuffer() {
+ if (mName && mAllocated) {
+ glDeleteRenderbuffers(1, &mName);
+ }
+ }
+
+ /**
+ * Returns the GL name of this render buffer.
+ */
+ GLuint getName() const {
+ return mName;
+ }
+
+ /**
+ * Returns the format of this render buffer.
+ */
+ GLenum getFormat() const {
+ return mFormat;
+ }
+
+ /**
+ * Binds this render buffer to the current GL context.
+ */
+ void bind() const {
+ glBindRenderbuffer(GL_RENDERBUFFER, mName);
+ }
+
+ /**
+ * Indicates whether this render buffer has allocated its
+ * storage. See allocate() and resize().
+ */
+ bool isAllocated() const {
+ return mAllocated;
+ }
+
+ /**
+ * Allocates this render buffer's storage if needed.
+ * This method doesn't do anything if isAllocated() returns true.
+ */
+ void allocate() {
+ if (!mAllocated) {
+ glRenderbufferStorage(GL_RENDERBUFFER, mFormat, mWidth, mHeight);
+ mAllocated = true;
+ }
+ }
+
+ /**
+ * Resizes this render buffer. If the buffer was previously allocated,
+ * the storage is re-allocated wit the new specified dimensions. If the
+ * buffer wasn't previously allocated, the buffer remains unallocated.
+ */
+ void resize(uint32_t width, uint32_t height) {
+ if (isAllocated() && (width != mWidth || height != mHeight)) {
+ glRenderbufferStorage(GL_RENDERBUFFER, mFormat, width, height);
+ }
+
+ mWidth = width;
+ mHeight = height;
+ }
+
+ /**
+ * Returns the width of the render buffer in pixels.
+ */
+ uint32_t getWidth() const {
+ return mWidth;
+ }
+
+ /**
+ * Returns the height of the render buffer in pixels.
+ */
+ uint32_t getHeight() const {
+ return mHeight;
+ }
+
+ /**
+ * Returns the size of this render buffer in bytes.
+ */
+ uint32_t getSize() const {
+ // Round to the nearest byte
+ return (uint32_t) ((mWidth * mHeight * formatSize(mFormat)) / 8.0f + 0.5f);
+ }
+
+ /**
+ * Returns the number of bits per component in the specified format.
+ * The format must be one of the formats allowed by glRenderbufferStorage().
+ */
+ static uint32_t formatSize(GLenum format) {
+ switch (format) {
+ case GL_STENCIL_INDEX8:
+ return 8;
+ case GL_STENCIL_INDEX1_OES:
+ return 1;
+ case GL_STENCIL_INDEX4_OES:
+ return 4;
+ case GL_DEPTH_COMPONENT16:
+ case GL_RGBA4:
+ case GL_RGB565:
+ case GL_RGB5_A1:
+ return 16;
+ }
+ return 0;
+ }
+
+ /**
+ * Indicates whether the specified format represents a stencil buffer.
+ */
+ static bool isStencilBuffer(GLenum format) {
+ switch (format) {
+ case GL_STENCIL_INDEX8:
+ case GL_STENCIL_INDEX1_OES:
+ case GL_STENCIL_INDEX4_OES:
+ return true;
+ }
+ return false;
+ }
+
+private:
+ GLenum mFormat;
+
+ uint32_t mWidth;
+ uint32_t mHeight;
+
+ bool mAllocated;
+
+ GLuint mName;
+}; // struct RenderBuffer
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_RENDER_BUFFER_H
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 87ed825b8d2df..19a5db75b5df1 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -183,6 +183,9 @@ const Rect& Snapshot::getLocalClip() {
}
void Snapshot::resetClip(float left, float top, float right, float bottom) {
+ // TODO: This is incorrect, when we start rendering into a new layer,
+ // we may have to modify the previous snapshot's clip rect and clip
+ // region if the previous restore() call did not restore the clip
clipRect = &mClipRectRoot;
clipRegion = &mClipRegionRoot;
setClip(left, top, right, bottom);
diff --git a/libs/hwui/Stencil.cpp b/libs/hwui/Stencil.cpp
index 4fcd51d6a7f41..ba2e6f2670e32 100644
--- a/libs/hwui/Stencil.cpp
+++ b/libs/hwui/Stencil.cpp
@@ -14,14 +14,23 @@
* limitations under the License.
*/
-#include
-
+#include "Extensions.h"
#include "Properties.h"
#include "Stencil.h"
+#include
+
namespace android {
namespace uirenderer {
+#if DEBUG_STENCIL
+#define STENCIL_WRITE_VALUE 0xff
+#define STENCIL_MASK_VALUE 0xff
+#else
+#define STENCIL_WRITE_VALUE 0x1
+#define STENCIL_MASK_VALUE 0x1
+#endif
+
Stencil::Stencil(): mState(kDisabled) {
}
@@ -29,6 +38,18 @@ uint32_t Stencil::getStencilSize() {
return STENCIL_BUFFER_SIZE;
}
+GLenum Stencil::getSmallestStencilFormat() {
+#if !DEBUG_STENCIL
+ const Extensions& extensions = Extensions::getInstance();
+ if (extensions.has1BitStencil()) {
+ return GL_STENCIL_INDEX1_OES;
+ } else if (extensions.has4BitStencil()) {
+ return GL_STENCIL_INDEX4_OES;
+ }
+#endif
+ return GL_STENCIL_INDEX8;
+}
+
void Stencil::clear() {
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
@@ -37,7 +58,7 @@ void Stencil::clear() {
void Stencil::enableTest() {
if (mState != kTest) {
enable();
- glStencilFunc(GL_EQUAL, 0xff, 0xff);
+ glStencilFunc(GL_EQUAL, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE);
// We only want to test, let's keep everything
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -48,7 +69,7 @@ void Stencil::enableTest() {
void Stencil::enableWrite() {
if (mState != kWrite) {
enable();
- glStencilFunc(GL_ALWAYS, 0xff, 0xff);
+ glStencilFunc(GL_ALWAYS, STENCIL_WRITE_VALUE, STENCIL_MASK_VALUE);
// The test always passes so the first two values are meaningless
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
diff --git a/libs/hwui/Stencil.h b/libs/hwui/Stencil.h
index 2f8a66a546934..047f7ee111a0d 100644
--- a/libs/hwui/Stencil.h
+++ b/libs/hwui/Stencil.h
@@ -21,6 +21,8 @@
#define LOG_TAG "OpenGLRenderer"
#endif
+#include
+
#include
namespace android {
@@ -40,6 +42,11 @@ public:
*/
ANDROID_API static uint32_t getStencilSize();
+ /**
+ * Returns the smallest stencil format accepted by render buffers.
+ */
+ static GLenum getSmallestStencilFormat();
+
/**
* Clears the stencil buffer.
*/
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index abf2d98f19013..5cff5a552aed7 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -219,7 +219,7 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege
// We could also enable mipmapping if both bitmap dimensions are powers
// of 2 but we'd have to deal with size changes. Let's keep this simple
- const bool canMipMap = Caches::getInstance().extensions.hasNPot();
+ const bool canMipMap = Extensions::getInstance().hasNPot();
// If the texture had mipmap enabled but not anymore,
// force a glTexImage2D to discard the mipmap levels
From 9748ef40cd7caac2718d640228e3455a63410924 Mon Sep 17 00:00:00 2001
From: Robert Greenwalt
Date: Mon, 11 Feb 2013 15:25:10 -0800
Subject: [PATCH 10/18] Reintroduce the net.dns system properties
Removing these properties broke video playback as they used
a custom dns resolver. We'll work together to resolve our
resolver issues in the future, but this was the easy fix to
get things working again.
bug:8173236
Change-Id: I687dae59eda4fc449efc34eed11c3dc88a110ad0
---
.../java/com/android/server/ConnectivityService.java | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index fb81391edd7ba..6efe4c5842e03 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -200,6 +200,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private int mDefaultConnectionSequence = 0;
private Object mDnsLock = new Object();
+ private int mNumDnsEntries;
private boolean mDnsOverridden = false;
private boolean mTestMode;
@@ -2479,6 +2480,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
try {
mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
mNetd.setDefaultInterfaceForDns(iface);
+ for (InetAddress dns : dnses) {
+ ++last;
+ String key = "net.dns" + last;
+ String value = dns.getHostAddress();
+ SystemProperties.set(key, value);
+ }
+ for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+ String key = "net.dns" + i;
+ SystemProperties.set(key, "");
+ }
+ mNumDnsEntries = last;
} catch (Exception e) {
if (DBG) loge("exception setting default dns interface: " + e);
}
From be46c86dc03a321cbf7128be6b2d197f9707f99d Mon Sep 17 00:00:00 2001
From: Winson Chung
Date: Mon, 11 Feb 2013 14:58:45 -0800
Subject: [PATCH 11/18] Manually recycling bitmap memory when rotating ss,
resetting canvas bitmap, adding logging. (Bug 7974275)
Change-Id: I1b0590a297610ee5fee4e68222144780ab6e55ec
---
.../systemui/screenshot/GlobalScreenshot.java | 32 +++++++++++++++++++
.../screenshot/TakeScreenshotService.java | 4 +++
2 files changed, 36 insertions(+)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 280b36829496c..ddfaad5296ef1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -45,6 +45,7 @@ import android.os.Environment;
import android.os.Process;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -86,6 +87,8 @@ class SaveImageInBackgroundData {
*/
class SaveImageInBackgroundTask extends AsyncTask {
+ private static final String TAG = "SaveImageInBackgroundTask";
+
private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
@@ -138,6 +141,7 @@ class SaveImageInBackgroundTask extends AsyncTask
Date: Mon, 11 Feb 2013 18:01:20 -0800
Subject: [PATCH 12/18] Prevent crash when setting up a stencil-based clip Bug
#8177690
Clear the layers before we setup the stencil to avoid dereferencing
the recently deleted rects.
Change-Id: I5dce5f965672f276f9490636d85b6018d3ab9422
---
libs/hwui/OpenGLRenderer.cpp | 7 +++++--
libs/hwui/font/Font.cpp | 5 ++++-
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 08e2332df80bc..62f268dab2912 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1179,6 +1179,10 @@ void OpenGLRenderer::clearLayerRegions() {
delete bounds;
}
+ // We must clear the list of dirty rects before we
+ // call setupDraw() to prevent stencil setup to do
+ // the same thing again
+ mLayers.clear();
setupDraw(false);
setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
@@ -1195,9 +1199,8 @@ void OpenGLRenderer::clearLayerRegions() {
for (uint32_t i = 0; i < count; i++) {
delete mLayers.itemAt(i);
}
+ mLayers.clear();
}
-
- mLayers.clear();
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 1afcb46d998cc..1a75ea8d272f6 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -189,7 +189,10 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float
vOffset += glyph->mBitmapTop + height;
SkPoint destination[4];
- measure.getPosTan(x + hOffset + glyph->mBitmapLeft + halfWidth, position, tangent);
+ bool ok = measure.getPosTan(x + hOffset + glyph->mBitmapLeft + halfWidth, position, tangent);
+ if (!ok) {
+ ALOGW("The path for drawTextOnPath is empty or null");
+ }
// Move along the tangent and offset by the normal
destination[0].set(-tangent->fX * halfWidth - tangent->fY * vOffset,
From 03dde4b9e09b00c23b6650925fd43a3421a67db5 Mon Sep 17 00:00:00 2001
From: Philip Milne
Date: Wed, 13 Feb 2013 22:07:50 +0000
Subject: [PATCH 13/18] Revert "Fix for bug: 8184401 - GridLayout accounts for
child's size/measurements even when a child is "GONE""
Suspected cause of: http://b.corp.google.com/issue?id=8192858
This reverts commit e5e0b7f191b64380e9231a2b755ecd3738598dec
Change-Id: I1a35c12c3ca0b1eacfb0c1a4d6ba03601dab664b
---
core/java/android/widget/GridLayout.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 12cce8bdd412a..85ed8dbd4927e 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -1235,7 +1235,6 @@ public class GridLayout extends ViewGroup {
Assoc assoc = Assoc.of(Spec.class, Bounds.class);
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
- if (c.getVisibility() == View.GONE) continue;
LayoutParams lp = getLayoutParams(c);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
Bounds bounds = getAlignment(spec.alignment, horizontal).getBounds();
@@ -1251,7 +1250,6 @@ public class GridLayout extends ViewGroup {
}
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
- if (c.getVisibility() == View.GONE) continue;
LayoutParams lp = getLayoutParams(c);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
groupBounds.getValue(i).include(GridLayout.this, c, spec, this);
From ca42382f36561d0d368fdd6a9601fb7a81198c1d Mon Sep 17 00:00:00 2001
From: Svetoslav
Date: Wed, 13 Feb 2013 14:55:19 -0800
Subject: [PATCH 14/18] Fixing a NPE in accessibility manager service.
There was a missing null checks as a result of a recent
refactoring.
bug:8185435
Change-Id: I3a1e256b434755b3a27f609dd2b6aeec31aa9a4f
---
.../server/accessibility/AccessibilityManagerService.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index aadb790dbae14..e6cabdc29d0d8 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -565,8 +565,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
UserState userState = getCurrentUserStateLocked();
// Automation service is not bound, so pretend it died to perform clean up.
if (userState.mUiAutomationService != null
- && userState.mUiAutomationService.mServiceInterface != null
&& serviceClient != null
+ && userState.mUiAutomationService != null
+ && userState.mUiAutomationService.mServiceInterface != null
&& userState.mUiAutomationService.mServiceInterface.asBinder()
== serviceClient.asBinder()) {
userState.mUiAutomationService.binderDied();
From 3d850df9b482ccd2ec42f28d8fba3a05bc381c96 Mon Sep 17 00:00:00 2001
From: Chris Craik
Date: Wed, 13 Feb 2013 10:25:12 -0800
Subject: [PATCH 15/18] Revert "Merge remote-tracking branch
'goog/master-chromium' into 'goog/master'" DO NOT MERGE
This reverts commit 6c0307dd0aefe9a08794b155fc03ee60ebd14f25, reversing
changes made to a2cd828b749c444d55c2c41c7dbb85088ff94b9f.
Conflicts:
packages/SystemUI/res/values-sv/strings.xml
Change-Id: Ia178efe8b14751583d47b2826bfe3d3d5463dd2e
---
core/java/android/view/GLES20Canvas.java | 8 +--
core/java/android/view/Surface.java | 1 +
core/jni/Android.mk | 3 +-
core/jni/android/graphics/BitmapFactory.cpp | 2 +-
core/jni/android/graphics/Canvas.cpp | 48 +++++++++--------
core/jni/android/graphics/NinePatchImpl.cpp | 2 +-
core/jni/android/graphics/Region.cpp | 6 +--
core/jni/android/graphics/TextLayoutCache.cpp | 2 +-
core/jni/android/graphics/Typeface.cpp | 20 +++++++
core/jni/android_view_GLES20Canvas.cpp | 5 +-
core/jni/android_view_Surface.cpp | 39 ++++++--------
core/jni/android_view_TextureView.cpp | 37 ++++---------
graphics/java/android/graphics/Canvas.java | 53 ++++++++-----------
graphics/java/android/graphics/Path.java | 4 +-
graphics/java/android/graphics/Typeface.java | 12 +++++
libs/hwui/Android.mk | 1 -
libs/hwui/DisplayListRenderer.h | 3 +-
libs/hwui/FontRenderer.cpp | 1 -
libs/hwui/Layer.h | 1 -
libs/hwui/OpenGLRenderer.cpp | 4 +-
libs/hwui/font/CacheTexture.cpp | 1 -
libs/hwui/font/Font.cpp | 1 -
media/tests/omxjpegdecoder/SkOmxPixelRef.h | 1 -
packages/SystemUI/res/values-sv/strings.xml | 2 +-
services/input/SpriteController.cpp | 3 +-
.../android/graphics/Typeface_Delegate.java | 5 ++
26 files changed, 131 insertions(+), 134 deletions(-)
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 80c9324aae996..80519231204f3 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -515,22 +515,22 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
- return nQuickReject(mRenderer, left, top, right, bottom);
+ return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt);
}
private static native boolean nQuickReject(int renderer, float left, float top,
- float right, float bottom);
+ float right, float bottom, int edge);
@Override
public boolean quickReject(Path path, EdgeType type) {
path.computeBounds(mPathBounds, true);
return nQuickReject(mRenderer, mPathBounds.left, mPathBounds.top,
- mPathBounds.right, mPathBounds.bottom);
+ mPathBounds.right, mPathBounds.bottom, type.nativeInt);
}
@Override
public boolean quickReject(RectF rect, EdgeType type) {
- return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
+ return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom, type.nativeInt);
}
///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index c10f28742888d..a972b750743ed 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -215,6 +215,7 @@ public class Surface implements Parcelable {
private int mNativeSurfaceControl; // SurfaceControl*
private int mGenerationId; // incremented each time mNativeSurface changes
private final Canvas mCanvas = new CompatibleCanvas();
+ private int mCanvasSaveCount; // Canvas save count at time of lockCanvas()
// The Translator for density compatibility mode. This is used for scaling
// the canvas to perform the appropriate density transformation.
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 44e87573af939..d705024166f28 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -160,8 +160,7 @@ LOCAL_C_INCLUDES += \
external/skia/include/effects \
external/skia/include/images \
external/skia/include/ports \
- external/skia/src/core \
- external/skia/src/images \
+ external/skia/src/ports \
external/skia/include/utils \
external/sqlite/dist \
external/sqlite/android \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index daabce3d8b105..b7fdecf9b7b4a 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -231,7 +231,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
}
SkAutoTDelete add(decoder);
- SkAutoTDelete adb(!useExistingBitmap ? bitmap : NULL);
+ SkAutoTDelete adb(bitmap, !useExistingBitmap);
decoder->setPeeker(&peeker);
if (!isPurgeable) {
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 7208c570f3911..5d6f73849b8c8 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -93,6 +93,14 @@ public:
return canvas->getDevice()->accessBitmap(false).height();
}
+ static void setBitmap(JNIEnv* env, jobject, SkCanvas* canvas, SkBitmap* bitmap) {
+ if (bitmap) {
+ canvas->setBitmapDevice(*bitmap);
+ } else {
+ canvas->setDevice(NULL);
+ }
+ }
+
static int saveAll(JNIEnv* env, jobject jcanvas) {
NPE_CHECK_RETURN_ZERO(env, jcanvas);
return GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
@@ -270,25 +278,25 @@ public:
canvas->setDrawFilter(filter);
}
- static jboolean quickReject__RectF(JNIEnv* env, jobject, SkCanvas* canvas,
- jobject rect) {
+ static jboolean quickReject__RectFI(JNIEnv* env, jobject, SkCanvas* canvas,
+ jobject rect, int edgetype) {
SkRect rect_;
GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
- return canvas->quickReject(rect_);
+ return canvas->quickReject(rect_, (SkCanvas::EdgeType)edgetype);
}
-
- static jboolean quickReject__Path(JNIEnv* env, jobject, SkCanvas* canvas,
- SkPath* path) {
- return canvas->quickReject(*path);
+
+ static jboolean quickReject__PathI(JNIEnv* env, jobject, SkCanvas* canvas,
+ SkPath* path, int edgetype) {
+ return canvas->quickReject(*path, (SkCanvas::EdgeType)edgetype);
}
-
- static jboolean quickReject__FFFF(JNIEnv* env, jobject, SkCanvas* canvas,
+
+ static jboolean quickReject__FFFFI(JNIEnv* env, jobject, SkCanvas* canvas,
jfloat left, jfloat top, jfloat right,
- jfloat bottom) {
+ jfloat bottom, int edgetype) {
SkRect r;
r.set(SkFloatToScalar(left), SkFloatToScalar(top),
SkFloatToScalar(right), SkFloatToScalar(bottom));
- return canvas->quickReject(r);
+ return canvas->quickReject(r, (SkCanvas::EdgeType)edgetype);
}
static void drawRGB(JNIEnv* env, jobject, SkCanvas* canvas,
@@ -930,19 +938,12 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
jobject bounds) {
SkRect r;
SkIRect ir;
- bool result = canvas->getClipBounds(&r);
+ bool result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
if (!result) {
r.setEmpty();
- } else {
- // ensure the clip is not larger than the canvas
- SkRect canvasRect;
- SkISize deviceSize = canvas->getDeviceSize();
- canvasRect.iset(0, 0, deviceSize.fWidth, deviceSize.fHeight);
- r.intersect(canvasRect);
}
r.round(&ir);
-
(void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
return result;
}
@@ -959,6 +960,7 @@ static JNINativeMethod gCanvasMethods[] = {
{"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
{"getWidth","()I", (void*) SkCanvasGlue::getWidth},
{"getHeight","()I", (void*) SkCanvasGlue::getHeight},
+ {"native_setBitmap","(II)V", (void*) SkCanvasGlue::setBitmap},
{"save","()I", (void*) SkCanvasGlue::saveAll},
{"save","(I)I", (void*) SkCanvasGlue::save},
{"native_saveLayer","(ILandroid/graphics/RectF;II)I",
@@ -990,10 +992,10 @@ static JNINativeMethod gCanvasMethods[] = {
{"native_getClipBounds","(ILandroid/graphics/Rect;)Z",
(void*) SkCanvasGlue::getClipBounds},
{"native_getCTM", "(II)V", (void*)SkCanvasGlue::getCTM},
- {"native_quickReject","(ILandroid/graphics/RectF;)Z",
- (void*) SkCanvasGlue::quickReject__RectF},
- {"native_quickReject","(II)Z", (void*) SkCanvasGlue::quickReject__Path},
- {"native_quickReject","(IFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
+ {"native_quickReject","(ILandroid/graphics/RectF;I)Z",
+ (void*) SkCanvasGlue::quickReject__RectFI},
+ {"native_quickReject","(III)Z", (void*) SkCanvasGlue::quickReject__PathI},
+ {"native_quickReject","(IFFFFI)Z", (void*)SkCanvasGlue::quickReject__FFFFI},
{"native_drawRGB","(IIII)V", (void*) SkCanvasGlue::drawRGB},
{"native_drawARGB","(IIIII)V", (void*) SkCanvasGlue::drawARGB},
{"native_drawColor","(II)V", (void*) SkCanvasGlue::drawColor__I},
diff --git a/core/jni/android/graphics/NinePatchImpl.cpp b/core/jni/android/graphics/NinePatchImpl.cpp
index 01e7e3e0eb6ad..ff0eb45b986dc 100644
--- a/core/jni/android/graphics/NinePatchImpl.cpp
+++ b/core/jni/android/graphics/NinePatchImpl.cpp
@@ -105,7 +105,7 @@ SkScalar calculateStretch(SkScalar boundsLimit, SkScalar startingPoint,
void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
const SkPaint* paint, SkRegion** outRegion) {
- if (canvas && canvas->quickReject(bounds)) {
+ if (canvas && canvas->quickReject(bounds, SkCanvas::kBW_EdgeType)) {
return;
}
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index ded21860b8b97..ab7cf4698c1ed 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -177,7 +177,7 @@ static SkRegion* Region_createFromParcel(JNIEnv* env, jobject clazz, jobject par
SkRegion* region = new SkRegion;
size_t size = p->readInt32();
- region->readFromMemory(p->readInplace(size));
+ region->unflatten(p->readInplace(size));
return region;
}
@@ -190,9 +190,9 @@ static jboolean Region_writeToParcel(JNIEnv* env, jobject clazz, const SkRegion*
android::Parcel* p = android::parcelForJavaObject(env, parcel);
- size_t size = region->writeToMemory(NULL);
+ size_t size = region->flatten(NULL);
p->writeInt32(size);
- region->writeToMemory(p->writeInplace(size));
+ region->flatten(p->writeInplace(size));
return true;
}
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 75446459665e1..6d3c87857dc5b 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -345,7 +345,7 @@ TextLayoutShaper::TextLayoutShaper() {
}
void TextLayoutShaper::init() {
- mDefaultTypeface = SkFontHost::CreateTypeface(NULL, NULL, SkTypeface::kNormal);
+ mDefaultTypeface = SkFontHost::CreateTypeface(NULL, NULL, NULL, 0, SkTypeface::kNormal);
}
void TextLayoutShaper::unrefTypefaces() {
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index e056b618bca45..7f4c37bff34db 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -147,6 +147,25 @@ static SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath)
return SkTypeface::CreateFromFile(str.c_str());
}
+#define MIN_GAMMA (0.1f)
+#define MAX_GAMMA (10.0f)
+static float pinGamma(float gamma) {
+ if (gamma < MIN_GAMMA) {
+ gamma = MIN_GAMMA;
+ } else if (gamma > MAX_GAMMA) {
+ gamma = MAX_GAMMA;
+ }
+ return gamma;
+}
+
+extern void skia_set_text_gamma(float, float);
+
+static void Typeface_setGammaForText(JNIEnv* env, jobject, jfloat blackGamma,
+ jfloat whiteGamma) {
+ // Comment this out for release builds. This is only used during development
+ skia_set_text_gamma(pinGamma(blackGamma), pinGamma(whiteGamma));
+}
+
///////////////////////////////////////////////////////////////////////////////
static JNINativeMethod gTypefaceMethods[] = {
@@ -158,6 +177,7 @@ static JNINativeMethod gTypefaceMethods[] = {
(void*)Typeface_createFromAsset },
{ "nativeCreateFromFile", "(Ljava/lang/String;)I",
(void*)Typeface_createFromFile },
+ { "setGammaForText", "(FF)V", (void*)Typeface_setGammaForText },
};
int register_android_graphics_Typeface(JNIEnv* env)
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 895a0dc61fea2..33ed0b95b5aaf 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -269,7 +269,8 @@ static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject cl
// ----------------------------------------------------------------------------
static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
- OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) {
+ OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
+ SkCanvas::EdgeType edge) {
return renderer->quickReject(left, top, right, bottom);
}
@@ -980,7 +981,7 @@ static JNINativeMethod gMethods[] = {
{ "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha },
{ "nSaveLayerAlpha", "(III)I", (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
- { "nQuickReject", "(IFFFF)Z", (void*) android_view_GLES20Canvas_quickReject },
+ { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
{ "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
{ "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
{ "nClipPath", "(III)Z", (void*) android_view_GLES20Canvas_clipPath },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index ed92e43c9ddba..1f1537082a906 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -66,6 +66,7 @@ static struct {
jfieldID mNativeSurfaceControl;
jfieldID mGenerationId;
jfieldID mCanvas;
+ jfieldID mCanvasSaveCount;
jmethodID ctor;
} gSurfaceClassInfo;
@@ -77,15 +78,10 @@ static struct {
} gRectClassInfo;
static struct {
- jfieldID mFinalizer;
jfieldID mNativeCanvas;
jfieldID mSurfaceFormat;
} gCanvasClassInfo;
-static struct {
- jfieldID mNativeCanvas;
-} gCanvasFinalizerClassInfo;
-
static struct {
jfieldID width;
jfieldID height;
@@ -139,7 +135,6 @@ public:
return mScreenshot.getFormat();
}
- SK_DECLARE_UNFLATTENABLE_OBJECT()
protected:
// overrides from SkPixelRef
virtual void* onLockPixels(SkColorTable** ct) {
@@ -378,15 +373,6 @@ static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
}
}
-static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
- jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
- SkCanvas* previousCanvas = reinterpret_cast(
- env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
- env->SetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas, (int)newCanvas);
- env->SetIntField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (int)newCanvas);
- SkSafeUnref(previousCanvas);
-}
-
static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) {
sp surface(getSurface(env, surfaceObj));
if (!Surface::isValid(surface)) {
@@ -423,6 +409,8 @@ static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRe
jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format);
+ SkCanvas* nativeCanvas = reinterpret_cast(
+ env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
SkBitmap bitmap;
ssize_t bpr = info.s * bytesPerPixel(info.format);
bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
@@ -435,9 +423,7 @@ static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRe
// be safe with an empty bitmap.
bitmap.setPixels(NULL);
}
-
- SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
- swapCanvasPtr(env, canvasObj, nativeCanvas);
+ nativeCanvas->setBitmapDevice(bitmap);
SkRegion clipReg;
if (dirtyRegion.isRect()) { // very common case
@@ -454,6 +440,9 @@ static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRe
nativeCanvas->clipRegion(clipReg);
+ int saveCount = nativeCanvas->save();
+ env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, saveCount);
+
if (dirtyRectObj) {
const Rect& bounds(dirtyRegion.getBounds());
env->SetIntField(dirtyRectObj, gRectClassInfo.left, bounds.left);
@@ -478,8 +467,12 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject c
}
// detach the canvas from the surface
- SkCanvas* nativeCanvas = SkNEW(SkCanvas);
- swapCanvasPtr(env, canvasObj, nativeCanvas);
+ SkCanvas* nativeCanvas = reinterpret_cast(
+ env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+ int saveCount = env->GetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount);
+ nativeCanvas->restoreToCount(saveCount);
+ nativeCanvas->setBitmapDevice(SkBitmap());
+ env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0);
// unlock surface
status_t err = surface->unlockAndPost();
@@ -895,16 +888,14 @@ int register_android_view_Surface(JNIEnv* env)
env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I");
gSurfaceClassInfo.mCanvas =
env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;");
+ gSurfaceClassInfo.mCanvasSaveCount =
+ env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I");
gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "", "()V");
clazz = env->FindClass("android/graphics/Canvas");
- gCanvasClassInfo.mFinalizer = env->GetFieldID(clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;");
gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
- clazz = env->FindClass("android/graphics/Canvas$CanvasFinalizer");
- gCanvasFinalizerClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
-
clazz = env->FindClass("android/graphics/Rect");
gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");
gRectClassInfo.top = env->GetFieldID(clazz, "top", "I");
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 64cbda3091a45..87b312f4cbfe7 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -43,15 +43,10 @@ static struct {
} gRectClassInfo;
static struct {
- jfieldID mFinalizer;
- jfieldID mNativeCanvas;
- jfieldID mSurfaceFormat;
+ jfieldID nativeCanvas;
+ jfieldID surfaceFormat;
} gCanvasClassInfo;
-static struct {
- jfieldID mNativeCanvas;
-} gCanvasFinalizerClassInfo;
-
static struct {
jfieldID nativeWindow;
} gTextureViewClassInfo;
@@ -125,15 +120,6 @@ static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject te
}
}
-static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
- jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
- SkCanvas* previousCanvas = reinterpret_cast(
- env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
- env->SetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas, (int)newCanvas);
- env->SetIntField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (int)newCanvas);
- SkSafeUnref(previousCanvas);
-}
-
static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
jint nativeWindow, jobject canvas, jobject dirtyRect) {
@@ -171,10 +157,9 @@ static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
bitmap.setPixels(NULL);
}
- SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format);
-
- SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
- swapCanvasPtr(env, canvas, nativeCanvas);
+ SET_INT(canvas, gCanvasClassInfo.surfaceFormat, buffer.format);
+ SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas);
+ nativeCanvas->setBitmapDevice(bitmap);
SkRect clipRect;
clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
@@ -189,8 +174,8 @@ static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
jint nativeWindow, jobject canvas) {
- SkCanvas* nativeCanvas = SkNEW(SkCanvas);
- swapCanvasPtr(env, canvas, nativeCanvas);
+ SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas);
+ nativeCanvas->setBitmapDevice(SkBitmap());
if (nativeWindow) {
sp window((ANativeWindow*) nativeWindow);
@@ -241,12 +226,8 @@ int register_android_view_TextureView(JNIEnv* env) {
GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I");
FIND_CLASS(clazz, "android/graphics/Canvas");
- GET_FIELD_ID(gCanvasClassInfo.mFinalizer, clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;");
- GET_FIELD_ID(gCanvasClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "I");
- GET_FIELD_ID(gCanvasClassInfo.mSurfaceFormat, clazz, "mSurfaceFormat", "I");
-
- FIND_CLASS(clazz, "android/graphics/Canvas$CanvasFinalizer");
- GET_FIELD_ID(gCanvasFinalizerClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "I");
+ GET_FIELD_ID(gCanvasClassInfo.nativeCanvas, clazz, "mNativeCanvas", "I");
+ GET_FIELD_ID(gCanvasClassInfo.surfaceFormat, clazz, "mSurfaceFormat", "I");
FIND_CLASS(clazz, "android/view/TextureView");
GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "I");
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 483d11afb8f3f..3949afdd4a2ae 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -37,8 +37,8 @@ import javax.microedition.khronos.opengles.GL;
* Canvas and Drawables developer guide.
*/
public class Canvas {
- // assigned in constructors or setBitmap, freed in finalizer
- int mNativeCanvas;
+ // assigned in constructors, freed in finalizer
+ final int mNativeCanvas;
// may be null
private Bitmap mBitmap;
@@ -83,7 +83,7 @@ public class Canvas {
private final CanvasFinalizer mFinalizer;
private static class CanvasFinalizer {
- private int mNativeCanvas;
+ private final int mNativeCanvas;
public CanvasFinalizer(int nativeCanvas) {
mNativeCanvas = nativeCanvas;
@@ -142,17 +142,6 @@ public class Canvas {
mDensity = Bitmap.getDefaultDensity();
}
- /**
- * Replace existing canvas while ensuring that the swap has occurred before
- * the previous native canvas is unreferenced.
- */
- private void safeCanvasSwap(int nativeCanvas) {
- final int oldCanvas = mNativeCanvas;
- mNativeCanvas = nativeCanvas;
- mFinalizer.mNativeCanvas = nativeCanvas;
- finalizer(oldCanvas);
- }
-
/**
* Returns null.
*
@@ -179,11 +168,11 @@ public class Canvas {
}
/**
- * Specify a bitmap for the canvas to draw into. As a side-effect, the
- * canvas' target density is updated to match that of the bitmap while all
- * other state such as the layers, filters, matrix, and clip are reset.
+ * Specify a bitmap for the canvas to draw into. As a side-effect, also
+ * updates the canvas's target density to match that of the bitmap.
*
* @param bitmap Specifies a mutable bitmap for the canvas to draw into.
+ *
* @see #setDensity(int)
* @see #getDensity()
*/
@@ -192,19 +181,17 @@ public class Canvas {
throw new RuntimeException("Can't set a bitmap device on a GL canvas");
}
- if (bitmap == null) {
- safeCanvasSwap(initRaster(0));
- mDensity = Bitmap.DENSITY_NONE;
- } else {
+ int pointer = 0;
+ if (bitmap != null) {
if (!bitmap.isMutable()) {
throw new IllegalStateException();
}
throwIfRecycled(bitmap);
-
- safeCanvasSwap(initRaster(bitmap.ni()));
mDensity = bitmap.mDensity;
+ pointer = bitmap.ni();
}
+ native_setBitmap(mNativeCanvas, pointer);
mBitmap = bitmap;
}
@@ -719,7 +706,7 @@ public class Canvas {
* does not intersect with the canvas' clip
*/
public boolean quickReject(RectF rect, EdgeType type) {
- return native_quickReject(mNativeCanvas, rect);
+ return native_quickReject(mNativeCanvas, rect, type.nativeInt);
}
/**
@@ -739,7 +726,7 @@ public class Canvas {
* does not intersect with the canvas' clip
*/
public boolean quickReject(Path path, EdgeType type) {
- return native_quickReject(mNativeCanvas, path.ni());
+ return native_quickReject(mNativeCanvas, path.ni(), type.nativeInt);
}
/**
@@ -762,9 +749,9 @@ public class Canvas {
* @return true if the rect (transformed by the canvas' matrix)
* does not intersect with the canvas' clip
*/
- public boolean quickReject(float left, float top, float right, float bottom,
- EdgeType type) {
- return native_quickReject(mNativeCanvas, left, top, right, bottom);
+ public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
+ return native_quickReject(mNativeCanvas, left, top, right, bottom,
+ type.nativeInt);
}
/**
@@ -1638,6 +1625,7 @@ public class Canvas {
public static native void freeTextLayoutCaches();
private static native int initRaster(int nativeBitmapOrZero);
+ private static native void native_setBitmap(int nativeCanvas, int bitmap);
private static native int native_saveLayer(int nativeCanvas, RectF bounds,
int paint, int layerFlags);
private static native int native_saveLayer(int nativeCanvas, float l,
@@ -1668,12 +1656,15 @@ public class Canvas {
Rect bounds);
private static native void native_getCTM(int canvas, int matrix);
private static native boolean native_quickReject(int nativeCanvas,
- RectF rect);
+ RectF rect,
+ int native_edgeType);
private static native boolean native_quickReject(int nativeCanvas,
- int path);
+ int path,
+ int native_edgeType);
private static native boolean native_quickReject(int nativeCanvas,
float left, float top,
- float right, float bottom);
+ float right, float bottom,
+ int native_edgeType);
private static native void native_drawRGB(int nativeCanvas, int r, int g,
int b);
private static native void native_drawARGB(int nativeCanvas, int a, int r,
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 157c7d1470cda..f6b5ffc9ad7ca 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -375,9 +375,9 @@ public class Path {
*/
public enum Direction {
/** clockwise */
- CW (1), // must match enum in SkPath.h
+ CW (0), // must match enum in SkPath.h
/** counter-clockwise */
- CCW (2); // must match enum in SkPath.h
+ CCW (1); // must match enum in SkPath.h
Direction(int ni) {
nativeInt = ni;
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index c68c9f7dd9fd1..4487a3c473287 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -225,4 +225,16 @@ public class Typeface {
private static native int nativeGetStyle(int native_instance);
private static native int nativeCreateFromAsset(AssetManager mgr, String path);
private static native int nativeCreateFromFile(String path);
+
+ /**
+ * Set the global gamma coefficients for black and white text. This call is
+ * usually a no-op in shipping products, and only exists for testing during
+ * development.
+ *
+ * @param blackGamma gamma coefficient for black text
+ * @param whiteGamma gamma coefficient for white text
+ *
+ * @hide - this is just for calibrating devices, not for normal apps
+ */
+ public static native void setGammaForText(float blackGamma, float whiteGamma);
}
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 2111a56578c2f..9a36f71f30cb9 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -43,7 +43,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
external/skia/include/core \
external/skia/include/effects \
external/skia/include/images \
- external/skia/src/core \
external/skia/src/ports \
external/skia/include/utils
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index f3bd188ea1910..b25288b1f0594 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -18,8 +18,7 @@
#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
#include
-#include
-#include
+#include
#include
#include
#include
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index d8297daeb636b..97988f78454bf 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -16,7 +16,6 @@
#define LOG_TAG "OpenGLRenderer"
-#include
#include
#include
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index ccf1da5539aaa..664b2f84b6f6b 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -23,7 +23,6 @@
#include
-#include
#include
#include "Rect.h"
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 62f268dab2912..aea37c4abe7a6 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -80,7 +80,7 @@ static const Blender gBlends[] = {
{ SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
{ SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
{ SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
- { SkXfermode::kModulate_Mode, GL_ZERO, GL_SRC_COLOR },
+ { SkXfermode::kMultiply_Mode, GL_ZERO, GL_SRC_COLOR },
{ SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
};
@@ -101,7 +101,7 @@ static const Blender gBlendsSwap[] = {
{ SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
{ SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
{ SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
- { SkXfermode::kModulate_Mode, GL_DST_COLOR, GL_ZERO },
+ { SkXfermode::kMultiply_Mode, GL_DST_COLOR, GL_ZERO },
{ SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE }
};
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index 24b0523cc7e10..f653592177681 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include
#include
#include "Debug.h"
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 1a75ea8d272f6..8c5a8ff90b223 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -20,7 +20,6 @@
#include
-#include
#include
#include "Debug.h"
diff --git a/media/tests/omxjpegdecoder/SkOmxPixelRef.h b/media/tests/omxjpegdecoder/SkOmxPixelRef.h
index 374604c39dae7..afedcbdf53cd3 100644
--- a/media/tests/omxjpegdecoder/SkOmxPixelRef.h
+++ b/media/tests/omxjpegdecoder/SkOmxPixelRef.h
@@ -33,7 +33,6 @@ public:
//! Return the allocation size for the pixels
size_t getSize() const { return mSize; }
- SK_DECLARE_UNFLATTENABLE_OBJECT()
protected:
// overrides from SkPixelRef
virtual void* onLockPixels(SkColorTable**);
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index a58c9a0158939..a03ca3314c0ab 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -196,7 +196,7 @@
"Wi-Fi"
"Ej ansluten"
"Inget nätverk"
- "Wi-Fi av"
+ "Wi-Fi är inaktiverat"
"Trådlös skärm"
"Trådlös skärm"
"Ljusstyrka"
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
index 8163ea0aa1fcb..1f3d2cf2fdf03 100644
--- a/services/input/SpriteController.cpp
+++ b/services/input/SpriteController.cpp
@@ -208,7 +208,8 @@ void SpriteController::doUpdateSprites() {
surfaceInfo.w, surfaceInfo.h, bpr);
surfaceBitmap.setPixels(surfaceInfo.bits);
- SkCanvas surfaceCanvas(surfaceBitmap);
+ SkCanvas surfaceCanvas;
+ surfaceCanvas.setBitmapDevice(surfaceBitmap);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 8701cc8068a65..2414d705be8a4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -188,6 +188,11 @@ public final class Typeface_Delegate {
return delegate.mStyle;
}
+ @LayoutlibDelegate
+ /*package*/ static void setGammaForText(float blackGamma, float whiteGamma) {
+ // This is for device testing only: pass
+ }
+
// ---- Private delegate/helper methods ----
private Typeface_Delegate(String family, int style) {
From a514b4fe809c1d0cf69dab23776f5ee20c4058c9 Mon Sep 17 00:00:00 2001
From: Svetoslav
Date: Wed, 13 Feb 2013 15:47:29 -0800
Subject: [PATCH 16/18] Proper clean up when Ui test automation service is
unregistered or dies.
The UI test automation service was not removed from the list of
enabled and installed service where it was explicitly added on
registration. This was leaving the accessibility manager service
in an inconsistent state.
bug:8185435
Change-Id: Ice17cdef361fe98ce34f8dd01ec11dbad6c4d0c2
---
.../server/accessibility/AccessibilityManagerService.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index e6cabdc29d0d8..e5cba625e4d3f 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2105,6 +2105,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (mIsAutomation) {
// We no longer have an automation service, so restore
// the state based on values in the settings database.
+ userState.mInstalledServices.remove(mAccessibilityServiceInfo);
+ userState.mEnabledServices.remove(mComponentName);
userState.mUiAutomationService = null;
userState.mUiAutomationServiceClient = null;
}
From ef60fa95b2928a6d25fd588c3945ea75642896aa Mon Sep 17 00:00:00 2001
From: Victoria Lease
Date: Thu, 14 Feb 2013 15:58:46 -0800
Subject: [PATCH 17/18] fix argument mismatches in Paint JNI
Paint.getTextRunCursor() no longer has a "flags" argument on the Java
side. The native side, however, still had the argument, and was being
called with misaligned arguments, causing all manner of madcap fun.
Also, the version of Paint.getTextRunCursor() that took String as an
argument needed to lose the "flags" argument, as well, to prevent an
infinite loop in the CharSequence version of the function, which was
supposed to be calling the String version but was actually calling
itself.
Bug: 8201224
Change-Id: Iad0dabaf81185f29a082566cc64590f2ba9bc31c
---
core/jni/android/graphics/Paint.cpp | 10 +++++-----
graphics/java/android/graphics/Paint.java | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index e8304923230fe..07f55e03f2d77 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -548,7 +548,7 @@ public:
}
static jint doTextRunCursor(JNIEnv *env, SkPaint* paint, const jchar *text, jint start,
- jint count, jint flags, jint offset, jint opt) {
+ jint count, jint offset, jint opt) {
jfloat scalarArray[count];
TextLayout::getTextRunAdvances(paint, text, start, count, start + count,
@@ -592,19 +592,19 @@ public:
}
static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, SkPaint* paint, jcharArray text,
- jint contextStart, jint contextCount, jint flags, jint offset, jint cursorOpt) {
+ jint contextStart, jint contextCount, jint offset, jint cursorOpt) {
jchar* textArray = env->GetCharArrayElements(text, NULL);
- jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, flags,
+ jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount,
offset, cursorOpt);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
return result;
}
static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text,
- jint contextStart, jint contextEnd, jint flags, jint offset, jint cursorOpt) {
+ jint contextStart, jint contextEnd, jint offset, jint cursorOpt) {
const jchar* textArray = env->GetStringChars(text, NULL);
jint result = doTextRunCursor(env, paint, textArray, contextStart,
- contextEnd - contextStart, flags, offset, cursorOpt);
+ contextEnd - contextStart, offset, cursorOpt);
env->ReleaseStringChars(text, textArray);
return result;
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 3a83d121516ee..7d99fece6f35e 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1849,7 +1849,7 @@ public class Paint {
* @hide
*/
public int getTextRunCursor(String text, int contextStart, int contextEnd,
- int flags, int offset, int cursorOpt) {
+ int offset, int cursorOpt) {
if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
| (offset - contextStart) | (contextEnd - offset)
| (text.length() - contextEnd) | cursorOpt) < 0)
From 169d8a96304cdf5a90b43bbb63b1a36c2b2856fb Mon Sep 17 00:00:00 2001
From: Jeff Sharkey
Date: Tue, 19 Feb 2013 13:01:35 -0800
Subject: [PATCH 18/18] Add DUMP permission to SystemUI for bugreports.
Bug: 8223786
Change-Id: Ie91167eaaa299fb7f0affa386407765efe4965a4
---
packages/SystemUI/AndroidManifest.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b85121ea1700d..66080f304c714 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -10,6 +10,7 @@
+