Merge "Crash on non-eng builds due to lacking null check." into jb-mr2-dev
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3586573..acb3725 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1817,11 +1817,12 @@
false)) {
owner.mRequiredForAllUsers = true;
}
- String restrictedAccountType = sa.getString(com.android.internal.R.styleable
- .AndroidManifestApplication_restrictedAccountType);
- if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
- owner.mRestrictedAccountType = restrictedAccountType;
- }
+ }
+
+ String restrictedAccountType = sa.getString(com.android.internal.R.styleable
+ .AndroidManifestApplication_restrictedAccountType);
+ if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
+ owner.mRestrictedAccountType = restrictedAccountType;
}
String requiredAccountType = sa.getString(com.android.internal.R.styleable
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d2b11e4..0c7cf72 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -622,7 +622,7 @@
<string name="permlab_accessNotifications" msgid="7673416487873432268">"adgang til underretninger"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillader, at appen kan hente, undersøge og rydde underretninger, herunder dem, der er sendt af andre apps."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"forpligte sig til en underretningslyttertjeneste"</string>
- <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Tillader, at brugeren kan forpligte sig til en grænseflade for en underretningslyttertjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
+ <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Tillader brugeren at forpligte sig til en underretningslyttertjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærmen."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 09acbe1..485e1bf 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -559,8 +559,8 @@
<string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Permite que la aplicación modifique el estado de la conectividad de red."</string>
<string name="permlab_changeTetherState" msgid="5952584964373017960">"cambiar conectividad de anclaje a red"</string>
<string name="permdesc_changeTetherState" msgid="1524441344412319780">"Permite que la aplicación cambie el estado de la conectividad de red de anclaje."</string>
- <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"cambiar configuración de uso de datos de referencia"</string>
- <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permite que la aplicación cambie los ajustes de uso de datos de referencia."</string>
+ <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"cambiar configuración de uso de conexiones automáticas"</string>
+ <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permite que la aplicación cambie los ajustes de uso de conexiones automáticas."</string>
<string name="permlab_accessWifiState" msgid="5202012949247040011">"ver conexiones Wi-Fi"</string>
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite que la aplicación vea información sobre conexión a redes Wi-Fi (por ejemplo, si está habilitada la conexión Wi-Fi y el nombre de los dispositivos Wi-Fi conectados)."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"conectarse a redes Wi-Fi y desconectarse"</string>
@@ -569,14 +569,14 @@
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos de una red Wi-Fi que utilicen direcciones de multidifusión, no solo al tablet. Utiliza más batería que el modo de no multidifusión."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Permite que la aplicación reciba paquetes enviados a todos los dispositivos de una red Wi-Fi que utilicen direcciones de multidifusión, no solo al teléfono. Utiliza más batería que el modo de no multidifusión."</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"acceder a los ajustes de Bluetooth"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite que la aplicación configure el tablet Bluetooth local y que detecte dispositivos remotos y se sincronice con ellos."</string>
- <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite que la aplicación configure el teléfono Bluetooth local y que detecte dispositivos remotos y se sincronice con ellos."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite que la aplicación configure el tablet Bluetooth local y que detecte dispositivos remotos y se vincule con ellos."</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite que la aplicación configure el teléfono Bluetooth local y que detecte dispositivos remotos y se vincule con ellos."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"conectarse a WiMAX y desconectarse de esta red"</string>
<string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite que la aplicación determine si está habilitada la conexión WiMAX y obtenga información sobre las redes WiMAX que están conectadas."</string>
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Cambiar estado de WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que la aplicación conecte el tablet a redes WiMAX y lo desconecte de ellas."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que la aplicación conecte el teléfono a redes WiMAX y lo desconecte de ellas."</string>
- <string name="permlab_bluetooth" msgid="6127769336339276828">"sincronizarse con dispositivos Bluetooth"</string>
+ <string name="permlab_bluetooth" msgid="6127769336339276828">"vincular con dispositivos Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que la aplicación acceda a la configuración de Bluetooth del tablet y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que la aplicación acceda a la configuración de Bluetooth del teléfono y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"controlar Comunicación de campo cercano (NFC)"</string>
@@ -702,7 +702,7 @@
<string name="phoneTypeIsdn" msgid="8022453193171370337">"RDSI"</string>
<string name="phoneTypeMain" msgid="6766137010628326916">"Principal"</string>
<string name="phoneTypeOtherFax" msgid="8587657145072446565">"Otro fax"</string>
- <string name="phoneTypeRadio" msgid="4093738079908667513">"Radio"</string>
+ <string name="phoneTypeRadio" msgid="4093738079908667513">"Señal móvil"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"Télex"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Móvil del trabajo"</string>
@@ -1391,7 +1391,7 @@
<string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"Límite de datos móviles superado"</string>
<string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Límite de datos Wi-Fi superado"</string>
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Límite superado en <xliff:g id="SIZE">%s</xliff:g>"</string>
- <string name="data_usage_restricted_title" msgid="5965157361036321914">"Datos de referencia restringidos"</string>
+ <string name="data_usage_restricted_title" msgid="5965157361036321914">"Conexiones automáticas restringidas"</string>
<string name="data_usage_restricted_body" msgid="6741521330997452990">"Toca para eliminar la restricción."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificado de seguridad"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado es válido."</string>
@@ -1420,7 +1420,7 @@
<string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string>
<string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Teléfono"</string>
<string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string>
- <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces del conector"</string>
+ <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces de la base"</string>
<string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
<string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 0c11321..bdc0155 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -622,7 +622,7 @@
<string name="permlab_accessNotifications" msgid="7673416487873432268">"fikia arifa"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Huruhusu programu kurejesha, kuchunguza, na kuondoa arifa, ikiwa ni pamoja na zile zilizochapishwa na programu nyingine."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"unganisha kwenye huduma ya kisikilizi cha arifa"</string>
- <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Inaruhusu kishikilizi kuunganishwa kwenye kiolesura cha kiwango cha juu cha huduma ya kisikilizi cha arifa. Haipaswi kuhitajika tena kwa programu za kawaida."</string>
+ <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Inaruhusu kishikilizi kuunganishwa kwenye kusano cha kiwango cha juu cha huduma ya kisikilizi cha arifa. Haipaswi kuhitajika tena kwa programu za kawaida."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Weka kanuni za nenosiri"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Dhibiti urefu na vibambo vinavyoruhusiwa katika manenosiri ya kufungua skrini."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Chunguza majaribio ya kutofun gua skrini"</string>
@@ -1284,7 +1284,7 @@
<string name="submit" msgid="1602335572089911941">"Wasilisha"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mtindo wa gari umewezeshwa"</string>
<string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Gusa ili kutoka katika modi ya gari."</string>
- <string name="tethered_notification_title" msgid="3146694234398202601">"Amilisha uzuiaji au mahali maalum"</string>
+ <string name="tethered_notification_title" msgid="3146694234398202601">"Kushiriki au kusambaza intaneti kumewashwa"</string>
<string name="tethered_notification_message" msgid="6857031760103062982">"Gusa ili kusanidi."</string>
<string name="back_button_label" msgid="2300470004503343439">"Nyuma"</string>
<string name="next_button_label" msgid="1080555104677992408">"Ifuatayo"</string>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 8821a01..f2c0aa0 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -909,7 +909,7 @@
<!-- Declare that this application requires access to restricted accounts of a certain
type. The default value is null and restricted accounts won\'t be visible to this
application. The type should correspond to the account authenticator type, such as
- "com.google". Only usable by system apps. -->
+ "com.google". -->
<attr name="restrictedAccountType" format="string"/>
<!-- Declare that this application requires an account of a certain
type. The default value is null and indicates that the application can work without
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index ea29b7d..5d1990a 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -277,21 +277,13 @@
throw new RSIllegalArgumentException("Invalid usage combination.");
}
}
- if (t != null) {
- // don't need to account for USAGE_SHARED Allocations
- if ((usage & USAGE_SHARED) == 0) {
- int numBytes = t.getCount() * t.getElement().getBytesSize();
- rs.addAllocSizeForGC(numBytes);
- mGCSize = numBytes;
- }
- }
+
mType = t;
mUsage = usage;
if (t != null) {
updateCacheInfo(t);
}
-
}
private void validateIsInt32() {
@@ -355,12 +347,6 @@
mType.updateFromNative();
updateCacheInfo(mType);
}
- // don't need to account for USAGE_SHARED Allocations
- if ((mUsage & USAGE_SHARED) == 0) {
- int numBytes = mType.getCount() * mType.getElement().getBytesSize();
- mRS.addAllocSizeForGC(numBytes);
- mGCSize = numBytes;
- }
}
/**
@@ -1264,7 +1250,6 @@
if (type.getID(rs) == 0) {
throw new RSInvalidStateException("Bad Type");
}
-
int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
@@ -1414,6 +1399,7 @@
return alloc;
}
+
int id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
if (id == 0) {
throw new RSRuntimeException("Load failed.");
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index c2ebc9f..f464f9b 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -71,9 +71,6 @@
private int mID;
private boolean mDestroyed;
private String mName;
-
- int mGCSize;
-
RenderScript mRS;
/**
@@ -138,9 +135,6 @@
throw new RSInvalidStateException("Object already destroyed.");
}
mDestroyed = true;
- if (mGCSize != 0) {
- mRS.removeAllocSizeForGC(mGCSize);
- }
mRS.nObjDestroy(mID);
}
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 33639dc..6f614c3 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -18,9 +18,7 @@
import java.io.File;
import java.lang.reflect.Field;
-import java.util.concurrent.locks.*;
-import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -804,8 +802,6 @@
int mContext;
@SuppressWarnings({"FieldCanBeLocal"})
MessageThread mMessageThread;
- GCThread mGCThread;
-
Element mElement_U8;
Element mElement_I8;
@@ -1095,60 +1091,6 @@
}
}
- static class GCThread extends Thread {
- RenderScript mRS;
- boolean mRun = true;
-
- long currentSize = 0;
- long targetSize; // call System.gc after 512MB of allocs
-
- final Lock lock = new ReentrantLock();
- final Condition cond = lock.newCondition();
-
- GCThread(RenderScript rs) {
- super("RSGCThread");
- mRS = rs;
-
- }
-
- public void run() {
- ActivityManager am = (ActivityManager)mRS.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
- ActivityManager.MemoryInfo meminfo = new ActivityManager.MemoryInfo();
- am.getMemoryInfo(meminfo);
- targetSize = (long)(meminfo.totalMem * .5f);
-
- while(mRun) {
- System.gc();
- lock.lock();
- try {
- cond.awaitUninterruptibly();
- } finally {
- lock.unlock();
- }
- }
-
- Log.d(LOG_TAG, "GCThread exiting.");
- }
-
- public synchronized void addAllocSize(long bytes) {
- currentSize += bytes;
- if (currentSize >= targetSize) {
- lock.lock();
- try {
- cond.signal();
- } finally {
- lock.unlock();
- }
- }
- }
-
- public synchronized void removeAllocSize(long bytes) {
- currentSize -= bytes;
- }
-
- }
-
-
RenderScript(Context ctx) {
if (ctx != null) {
mApplicationContext = ctx.getApplicationContext();
@@ -1171,15 +1113,6 @@
return create(ctx, sdkVersion, ContextType.NORMAL);
}
- void addAllocSizeForGC(int bytes) {
- mGCThread.addAllocSize(bytes);
- }
-
- void removeAllocSizeForGC(int bytes) {
- mGCThread.removeAllocSize(bytes);
- }
-
-
/**
* Create a basic RenderScript context.
*
@@ -1196,9 +1129,7 @@
throw new RSDriverException("Failed to create RS context.");
}
rs.mMessageThread = new MessageThread(rs);
- rs.mGCThread = new GCThread(rs);
rs.mMessageThread.start();
- rs.mGCThread.start();
return rs;
}
@@ -1253,11 +1184,8 @@
validate();
nContextDeinitToClient(mContext);
mMessageThread.mRun = false;
- mGCThread.mRun = false;
- mGCThread.addAllocSize(0);
try {
mMessageThread.join();
- mGCThread.join();
} catch(InterruptedException e) {
}
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index fad8838..52034b1 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -198,9 +198,6 @@
}
mMessageThread = new MessageThread(this);
mMessageThread.start();
- mGCThread = new GCThread(this);
- mGCThread.start();
-
}
/**
diff --git a/graphics/java/android/renderscript/ScriptC.java b/graphics/java/android/renderscript/ScriptC.java
index 2f69775..221f760 100644
--- a/graphics/java/android/renderscript/ScriptC.java
+++ b/graphics/java/android/renderscript/ScriptC.java
@@ -60,8 +60,6 @@
throw new RSRuntimeException("Loading of ScriptC script failed.");
}
setID(id);
- mGCSize = 2 * 1024 * 1024;
- rs.addAllocSizeForGC(mGCSize);
}
/**
diff --git a/keystore/tests/src/android/security/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
index 05ffe109..507d41c 100644
--- a/keystore/tests/src/android/security/AndroidKeyStoreTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
@@ -504,11 +504,13 @@
assertAliases(new String[] {});
- assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1));
+ assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertAliases(new String[] { TEST_ALIAS_1 });
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 });
}
@@ -530,11 +532,13 @@
assertAliases(new String[] {});
- assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1));
+ assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should contain generated private key", mKeyStore.containsAlias(TEST_ALIAS_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_2));
@@ -547,7 +551,8 @@
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_2));
}
@@ -567,15 +572,19 @@
// TEST_ALIAS_1
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
// TEST_ALIAS_2
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
// TEST_ALIAS_3
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_3, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_3, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2, TEST_ALIAS_3 });
@@ -608,9 +617,11 @@
// TEST_ALIAS_1
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
// Should not throw when a non-existent entry is requested for delete.
mKeyStore.deleteEntry(TEST_ALIAS_2);
@@ -621,7 +632,8 @@
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertAliases(new String[] { TEST_ALIAS_1 });
@@ -652,7 +664,8 @@
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
CertificateFactory f = CertificateFactory.getInstance("X.509");
Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
@@ -668,9 +681,11 @@
mKeyStore.load(null, null);
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
CertificateFactory f = CertificateFactory.getInstance("X.509");
Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
@@ -686,13 +701,16 @@
mKeyStore.load(null, null);
// Insert TrustedCertificateEntry with CA name
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
// Insert PrivateKeyEntry that uses the same CA
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
CertificateFactory f = CertificateFactory.getInstance("X.509");
Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
@@ -719,7 +737,8 @@
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
CertificateFactory f = CertificateFactory.getInstance("X.509");
Certificate userCert = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
@@ -734,9 +753,11 @@
mKeyStore.load(null, null);
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate[] expected = new Certificate[2];
@@ -771,9 +792,11 @@
mKeyStore.load(null, null);
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
Date now = new Date();
Date actual = mKeyStore.getCreationDate(TEST_ALIAS_1);
@@ -810,7 +833,8 @@
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
Date now = new Date();
Date actual = mKeyStore.getCreationDate(TEST_ALIAS_1);
@@ -829,9 +853,11 @@
mKeyStore.load(null, null);
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
Entry entry = mKeyStore.getEntry(TEST_ALIAS_1, null);
assertNotNull("Entry should exist", entry);
@@ -930,9 +956,11 @@
mKeyStore.load(null, null);
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
assertNotNull("Key should exist", key);
@@ -977,7 +1005,8 @@
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertNull("Certificate entries should return null", mKeyStore.getKey(TEST_ALIAS_1, null));
}
@@ -1006,7 +1035,8 @@
setupPassword();
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should return true for CA certificate",
mKeyStore.isCertificateEntry(TEST_ALIAS_1));
@@ -1017,9 +1047,11 @@
mKeyStore.load(null, null);
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertFalse("Should return false for PrivateKeyEntry",
mKeyStore.isCertificateEntry(TEST_ALIAS_1));
@@ -1045,9 +1077,11 @@
mKeyStore.load(null, null);
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should return true for PrivateKeyEntry", mKeyStore.isKeyEntry(TEST_ALIAS_1));
}
@@ -1056,7 +1090,8 @@
setupPassword();
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertFalse("Should return false for CA certificate", mKeyStore.isKeyEntry(TEST_ALIAS_1));
}
@@ -1089,7 +1124,8 @@
setupPassword();
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertAliases(new String[] { TEST_ALIAS_1 });
@@ -1107,9 +1143,11 @@
mKeyStore.load(null, null);
assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
- FAKE_KEY_1));
- assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ FAKE_KEY_1, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertAliases(new String[] { TEST_ALIAS_1 });
@@ -1596,7 +1634,8 @@
// Create key #1
{
final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1;
- assertTrue(mAndroidKeyStore.generate(privateKeyAlias));
+ assertTrue(mAndroidKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
@@ -1608,7 +1647,7 @@
TEST_SERIAL_1, TEST_DN_1, NOW, NOW_PLUS_10_YEARS);
assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1,
- expectedCert.getEncoded()));
+ expectedCert.getEncoded(), KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
Entry entry = mKeyStore.getEntry(TEST_ALIAS_1, null);
@@ -1651,25 +1690,27 @@
// Create key #1
{
final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1;
- assertTrue(mAndroidKeyStore.generate(privateKeyAlias));
+ assertTrue(mAndroidKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_1,
TEST_SERIAL_1, TEST_DN_1, NOW, NOW_PLUS_10_YEARS);
assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1,
- cert.getEncoded()));
+ cert.getEncoded(), KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
}
// Create key #2
{
final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_2;
- assertTrue(mAndroidKeyStore.generate(privateKeyAlias));
+ assertTrue(mAndroidKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_2,
TEST_SERIAL_2, TEST_DN_2, NOW, NOW_PLUS_10_YEARS);
assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_2,
- cert.getEncoded()));
+ cert.getEncoded(), KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
}
// Replace key #1 with key #2
@@ -1731,17 +1772,20 @@
setupPassword();
mKeyStore.load(null, null);
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertEquals("The keystore size should match expected", 1, mKeyStore.size());
assertAliases(new String[] { TEST_ALIAS_1 });
- assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+ assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertEquals("The keystore size should match expected", 2, mKeyStore.size());
assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 });
- assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
+ assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3,
+ KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertEquals("The keystore size should match expected", 3, mKeyStore.size());
assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2, TEST_ALIAS_3 });
@@ -1807,13 +1851,14 @@
private void setupKey() throws Exception {
final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1;
- assertTrue(mAndroidKeyStore.generate(privateKeyAlias));
+ assertTrue(mAndroidKeyStore
+ .generate(privateKeyAlias, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_1, TEST_SERIAL_1,
TEST_DN_1, NOW, NOW_PLUS_10_YEARS);
assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1,
- cert.getEncoded()));
+ cert.getEncoded(), KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
}
public void testKeyStore_KeyOperations_Wrap_Encrypted_Success() throws Exception {
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 1de1eaf..815f4ac 100644
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -142,42 +142,51 @@
assertNull(mKeyStore.get(TEST_KEYNAME));
mKeyStore.password(TEST_PASSWD);
assertNull(mKeyStore.get(TEST_KEYNAME));
- assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
}
public void testPut() throws Exception {
assertNull(mKeyStore.get(TEST_KEYNAME));
- assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
mKeyStore.password(TEST_PASSWD);
- assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
}
public void testPut_grantedUid_Wifi() throws Exception {
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
- assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID));
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
mKeyStore.password(TEST_PASSWD);
- assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID));
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
}
public void testPut_ungrantedUid_Bluetooth() throws Exception {
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
- assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
mKeyStore.password(TEST_PASSWD);
- assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
}
public void testI18n() throws Exception {
- assertFalse(mKeyStore.put(TEST_I18N_KEY, TEST_I18N_VALUE));
+ assertFalse(mKeyStore.put(TEST_I18N_KEY, TEST_I18N_VALUE, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_I18N_KEY));
mKeyStore.password(TEST_I18N_KEY);
- assertTrue(mKeyStore.put(TEST_I18N_KEY, TEST_I18N_VALUE));
+ assertTrue(mKeyStore.put(TEST_I18N_KEY, TEST_I18N_VALUE, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_I18N_KEY));
}
@@ -186,7 +195,8 @@
mKeyStore.password(TEST_PASSWD);
assertFalse(mKeyStore.delete(TEST_KEYNAME));
- assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
assertTrue(mKeyStore.delete(TEST_KEYNAME));
assertNull(mKeyStore.get(TEST_KEYNAME));
@@ -197,7 +207,8 @@
mKeyStore.password(TEST_PASSWD);
assertFalse(mKeyStore.delete(TEST_KEYNAME, Process.WIFI_UID));
- assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID));
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
assertTrue(mKeyStore.delete(TEST_KEYNAME, Process.WIFI_UID));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
@@ -208,7 +219,8 @@
mKeyStore.password(TEST_PASSWD);
assertFalse(mKeyStore.delete(TEST_KEYNAME, Process.BLUETOOTH_UID));
- assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
assertFalse(mKeyStore.delete(TEST_KEYNAME, Process.BLUETOOTH_UID));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
@@ -220,7 +232,8 @@
assertTrue(mKeyStore.password(TEST_PASSWD));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
- assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, KeyStore.UID_SELF,
+ KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME));
}
@@ -230,7 +243,8 @@
assertTrue(mKeyStore.password(TEST_PASSWD));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
- assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID));
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
}
@@ -240,7 +254,8 @@
assertTrue(mKeyStore.password(TEST_PASSWD));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
- assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
}
@@ -250,8 +265,8 @@
assertEquals(0, emptyResult.length);
mKeyStore.password(TEST_PASSWD);
- mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE);
- mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE);
+ mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED);
+ mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED);
String[] results = mKeyStore.saw(TEST_KEYNAME);
assertEquals(new HashSet(Arrays.asList(TEST_KEYNAME1.substring(TEST_KEYNAME.length()),
@@ -264,8 +279,8 @@
assertNull(results1);
mKeyStore.password(TEST_PASSWD);
- mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE);
- mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE);
+ mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED);
+ mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED);
String[] results2 = mKeyStore.saw(TEST_KEYNAME, Process.BLUETOOTH_UID);
assertNull(results2);
@@ -277,8 +292,8 @@
assertEquals(0, results1.length);
mKeyStore.password(TEST_PASSWD);
- mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, Process.WIFI_UID);
- mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, Process.WIFI_UID);
+ mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, Process.WIFI_UID, KeyStore.FLAG_ENCRYPTED);
+ mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, Process.WIFI_UID, KeyStore.FLAG_ENCRYPTED);
String[] results2 = mKeyStore.saw(TEST_KEYNAME, Process.WIFI_UID);
assertEquals(new HashSet(Arrays.asList(TEST_KEYNAME1.substring(TEST_KEYNAME.length()),
@@ -292,8 +307,8 @@
assertEquals(0, results1.length);
mKeyStore.password(TEST_PASSWD);
- mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, Process.VPN_UID);
- mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, Process.VPN_UID);
+ mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, Process.VPN_UID, KeyStore.FLAG_ENCRYPTED);
+ mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, Process.VPN_UID, KeyStore.FLAG_ENCRYPTED);
String[] results2 = mKeyStore.saw(TEST_KEYNAME, Process.VPN_UID);
assertEquals(new HashSet(Arrays.asList(TEST_KEYNAME1.substring(TEST_KEYNAME.length()),
@@ -324,7 +339,7 @@
assertTrue(mKeyStore.isEmpty());
mKeyStore.password(TEST_PASSWD);
assertTrue(mKeyStore.isEmpty());
- mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
+ mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED);
assertFalse(mKeyStore.isEmpty());
mKeyStore.reset();
assertTrue(mKeyStore.isEmpty());
@@ -332,20 +347,21 @@
public void testGenerate_NotInitialized_Fail() throws Exception {
assertFalse("Should fail when keystore is not initialized",
- mKeyStore.generate(TEST_KEYNAME));
+ mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
}
public void testGenerate_Locked_Fail() throws Exception {
mKeyStore.password(TEST_PASSWD);
mKeyStore.lock();
- assertFalse("Should fail when keystore is locked", mKeyStore.generate(TEST_KEYNAME));
+ assertFalse("Should fail when keystore is locked",
+ mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
}
public void testGenerate_Success() throws Exception {
assertTrue(mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to generate key when unlocked",
- mKeyStore.generate(TEST_KEYNAME));
+ mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
}
@@ -354,7 +370,7 @@
assertTrue(mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to generate key when unlocked",
- mKeyStore.generate(TEST_KEYNAME, Process.WIFI_UID));
+ mKeyStore.generate(TEST_KEYNAME, Process.WIFI_UID, KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
}
@@ -362,7 +378,7 @@
public void testGenerate_ungrantedUid_Bluetooth_Failure() throws Exception {
assertTrue(mKeyStore.password(TEST_PASSWD));
- assertFalse(mKeyStore.generate(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.generate(TEST_KEYNAME, Process.BLUETOOTH_UID, KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
@@ -371,8 +387,8 @@
public void testImport_Success() throws Exception {
assertTrue(mKeyStore.password(TEST_PASSWD));
- assertTrue("Should be able to import key when unlocked",
- mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+ assertTrue("Should be able to import key when unlocked", mKeyStore.importKey(TEST_KEYNAME,
+ PRIVKEY_BYTES, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
}
@@ -380,8 +396,8 @@
public void testImport_grantedUid_Wifi_Success() throws Exception {
assertTrue(mKeyStore.password(TEST_PASSWD));
- assertTrue("Should be able to import key when unlocked",
- mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES, Process.WIFI_UID));
+ assertTrue("Should be able to import key when unlocked", mKeyStore.importKey(TEST_KEYNAME,
+ PRIVKEY_BYTES, Process.WIFI_UID, KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
}
@@ -389,7 +405,8 @@
public void testImport_ungrantedUid_Bluetooth_Failure() throws Exception {
assertTrue(mKeyStore.password(TEST_PASSWD));
- assertFalse(mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES, Process.BLUETOOTH_UID,
+ KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
@@ -398,8 +415,8 @@
public void testImport_Failure_BadEncoding() throws Exception {
mKeyStore.password(TEST_PASSWD);
- assertFalse("Invalid DER-encoded key should not be imported",
- mKeyStore.importKey(TEST_KEYNAME, TEST_DATA));
+ assertFalse("Invalid DER-encoded key should not be imported", mKeyStore.importKey(
+ TEST_KEYNAME, TEST_DATA, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
}
@@ -407,7 +424,7 @@
public void testSign_Success() throws Exception {
mKeyStore.password(TEST_PASSWD);
- assertTrue(mKeyStore.generate(TEST_KEYNAME));
+ assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME));
final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA);
@@ -417,7 +434,7 @@
public void testVerify_Success() throws Exception {
mKeyStore.password(TEST_PASSWD);
- assertTrue(mKeyStore.generate(TEST_KEYNAME));
+ assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME));
final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA);
@@ -444,7 +461,7 @@
mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to generate key for testcase",
- mKeyStore.generate(TEST_KEYNAME));
+ mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should be able to grant key to other user",
mKeyStore.grant(TEST_KEYNAME, 0));
@@ -453,8 +470,8 @@
public void testGrant_Imported_Success() throws Exception {
assertTrue("Password should work for keystore", mKeyStore.password(TEST_PASSWD));
- assertTrue("Should be able to import key for testcase",
- mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+ assertTrue("Should be able to import key for testcase", mKeyStore.importKey(TEST_KEYNAME,
+ PRIVKEY_BYTES, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should be able to grant key to other user", mKeyStore.grant(TEST_KEYNAME, 0));
}
@@ -477,7 +494,7 @@
mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to generate key for testcase",
- mKeyStore.generate(TEST_KEYNAME));
+ mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should be able to grant key to other user",
mKeyStore.grant(TEST_KEYNAME, 0));
@@ -490,8 +507,8 @@
assertTrue("Password should work for keystore",
mKeyStore.password(TEST_PASSWD));
- assertTrue("Should be able to import key for testcase",
- mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+ assertTrue("Should be able to import key for testcase", mKeyStore.importKey(TEST_KEYNAME,
+ PRIVKEY_BYTES, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should be able to grant key to other user",
mKeyStore.grant(TEST_KEYNAME, 0));
@@ -510,7 +527,7 @@
mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to generate key for testcase",
- mKeyStore.generate(TEST_KEYNAME));
+ mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertFalse("Should not be able to revoke not existent grant",
mKeyStore.ungrant(TEST_KEYNAME, 0));
@@ -521,7 +538,7 @@
mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to generate key for testcase",
- mKeyStore.generate(TEST_KEYNAME));
+ mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should be able to grant key to other user",
mKeyStore.grant(TEST_KEYNAME, 0));
@@ -538,7 +555,7 @@
mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to generate key for testcase",
- mKeyStore.generate(TEST_KEYNAME));
+ mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue("Should be able to grant key to other user",
mKeyStore.grant(TEST_KEYNAME, 0));
@@ -558,7 +575,7 @@
assertFalse(mKeyStore.contains(TEST_KEYNAME));
- assertTrue(mKeyStore.generate(TEST_KEYNAME));
+ assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
@@ -596,7 +613,7 @@
assertFalse(mKeyStore.contains(TEST_KEYNAME));
- assertTrue(mKeyStore.generate(TEST_KEYNAME));
+ assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertTrue(mKeyStore.contains(TEST_KEYNAME));
assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
@@ -619,8 +636,8 @@
assertTrue("Password should work for keystore",
mKeyStore.password(TEST_PASSWD));
- assertTrue("Should be able to import key when unlocked",
- mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+ assertTrue("Should be able to import key when unlocked", mKeyStore.importKey(TEST_KEYNAME,
+ PRIVKEY_BYTES, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
long now = System.currentTimeMillis();
long actual = mKeyStore.getmtime(TEST_KEYNAME);
@@ -650,8 +667,8 @@
assertTrue("Password should work for keystore",
mKeyStore.password(TEST_PASSWD));
- assertTrue("Should be able to import key when unlocked",
- mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+ assertTrue("Should be able to import key when unlocked", mKeyStore.importKey(TEST_KEYNAME,
+ PRIVKEY_BYTES, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED));
assertEquals("-1 should be returned for non-existent key",
-1L, mKeyStore.getmtime(TEST_KEYNAME2));
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 46beb94..790c4f4 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -84,6 +84,9 @@
// Turn on to insert an event marker for each display list op
#define DEBUG_DISPLAY_LIST_OPS_AS_EVENTS 0
+// Turn on to highlight drawing batches and merged batches with different colors
+#define DEBUG_MERGE_BEHAVIOR 0
+
#if DEBUG_INIT
#define INIT_LOGD(...) ALOGD(__VA_ARGS__)
#else
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index d5007e1..f0084f2 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -23,6 +23,7 @@
#include "Caches.h"
#include "Debug.h"
+#include "DeferredDisplayList.h"
#include "DisplayListOp.h"
#include "OpenGLRenderer.h"
@@ -38,15 +39,27 @@
// Depth of the save stack at the beginning of batch playback at flush time
#define FLUSH_SAVE_STACK_DEPTH 2
+#define DEBUG_COLOR_BARRIER 0x1f000000
+#define DEBUG_COLOR_MERGEDBATCH 0x5f7f7fff
+#define DEBUG_COLOR_MERGEDBATCH_SOLO 0x5f7fff7f
+
/////////////////////////////////////////////////////////////////////////////////
// Operation Batches
/////////////////////////////////////////////////////////////////////////////////
-class DrawOpBatch {
+class Batch {
public:
- DrawOpBatch() { mOps.clear(); }
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) = 0;
+ virtual ~Batch() {}
+};
- virtual ~DrawOpBatch() { mOps.clear(); }
+class DrawBatch : public Batch {
+public:
+ DrawBatch(int batchId, mergeid_t mergeId) : mBatchId(batchId), mMergeId(mergeId) {
+ mOps.clear();
+ }
+
+ virtual ~DrawBatch() { mOps.clear(); }
void add(DrawOp* op) {
// NOTE: ignore empty bounds special case, since we don't merge across those ops
@@ -54,7 +67,7 @@
mOps.add(op);
}
- virtual bool intersects(Rect& rect) {
+ bool intersects(Rect& rect) {
if (!rect.intersects(mBounds)) return false;
for (unsigned int i = 0; i < mOps.size(); i++) {
@@ -71,8 +84,9 @@
return false;
}
- virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
- DEFER_LOGD("replaying draw batch %p", this);
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) {
+ DEFER_LOGD("%d replaying DrawingBatch %p, with %d ops (batch id %x, merge id %p)",
+ index, this, mOps.size(), mOps[0]->getBatchId(), mOps[0]->getMergeId());
status_t status = DrawGlInfo::kStatusDone;
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
@@ -84,31 +98,127 @@
#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
renderer.eventMark(op->name());
#endif
- status |= op->applyDraw(renderer, dirty, 0);
+ status |= op->applyDraw(renderer, dirty);
logBuffer.writeCommand(0, op->name());
+
+#if DEBUG_MERGE_BEHAVIOR
+ Rect& bounds = mOps[i]->state.mBounds;
+ int batchColor = 0x1f000000;
+ if (getBatchId() & 0x1) batchColor |= 0x0000ff;
+ if (getBatchId() & 0x2) batchColor |= 0x00ff00;
+ if (getBatchId() & 0x4) batchColor |= 0xff0000;
+ renderer.drawScreenSpaceColorRect(bounds.left, bounds.top, bounds.right, bounds.bottom,
+ batchColor);
+#endif
}
return status;
}
+ inline int getBatchId() const { return mBatchId; }
+ inline mergeid_t getMergeId() const { return mMergeId; }
inline int count() const { return mOps.size(); }
-private:
+
+protected:
Vector<DrawOp*> mOps;
Rect mBounds;
+private:
+ int mBatchId;
+ mergeid_t mMergeId;
};
-class StateOpBatch : public DrawOpBatch {
+// compare alphas approximately, with a small margin
+#define NEQ_FALPHA(lhs, rhs) \
+ fabs((float)lhs - (float)rhs) > 0.001f
+
+class MergingDrawBatch : public DrawBatch {
+public:
+ MergingDrawBatch(int batchId, mergeid_t mergeId) : DrawBatch(batchId, mergeId) {}
+
+ /*
+ * Checks if a (mergeable) op can be merged into this batch
+ *
+ * If true, the op's multiDraw must be guaranteed to handle both ops simultaneously, so it is
+ * important to consider all paint attributes used in the draw calls in deciding both a) if an
+ * op tries to merge at all, and b) if the op
+ *
+ * False positives can lead to information from the paints of subsequent merged operations being
+ * dropped, so we make simplifying qualifications on the ops that can merge, per op type.
+ */
+ bool canMergeWith(DrawOp* op) {
+ if (!op->state.mMatrix.isPureTranslate()) return false;
+
+ bool isTextBatch = getBatchId() == DeferredDisplayList::kOpBatch_Text ||
+ getBatchId() == DeferredDisplayList::kOpBatch_ColorText;
+
+ // Overlapping other operations is only allowed for text without shadow. For other ops,
+ // multiDraw isn't guaranteed to overdraw correctly
+ if (!isTextBatch || op->state.mDrawModifiers.mHasShadow) {
+ if (intersects(op->state.mBounds)) return false;
+ }
+
+ const DeferredDisplayState& lhs = op->state;
+ const DeferredDisplayState& rhs = mOps[0]->state;
+
+ if (NEQ_FALPHA(lhs.mAlpha, rhs.mAlpha)) return false;
+
+ // if paints are equal, then modifiers + paint attribs don't need to be compared
+ if (op->mPaint == mOps[0]->mPaint) return true;
+
+ if (op->getPaintAlpha() != mOps[0]->getPaintAlpha()) return false;
+
+ /* Draw Modifiers compatibility check
+ *
+ * Shadows are ignored, as only text uses them, and in that case they are drawn
+ * per-DrawTextOp, before the unified text draw. Because of this, it's always safe to merge
+ * text UNLESS a later draw's shadow should overlays a previous draw's text. This is covered
+ * above with the intersection check.
+ *
+ * OverrideLayerAlpha is also ignored, as it's only used for drawing layers, which are never
+ * merged.
+ *
+ * These ignore cases prevent us from simply memcmp'ing the drawModifiers
+ */
+
+ const DrawModifiers& lhsMod = lhs.mDrawModifiers;
+ const DrawModifiers& rhsMod = rhs.mDrawModifiers;
+ if (lhsMod.mShader != rhsMod.mShader) return false;
+ if (lhsMod.mColorFilter != rhsMod.mColorFilter) return false;
+
+ // Draw filter testing expects bit fields to be clear if filter not set.
+ if (lhsMod.mHasDrawFilter != rhsMod.mHasDrawFilter) return false;
+ if (lhsMod.mPaintFilterClearBits != rhsMod.mPaintFilterClearBits) return false;
+ if (lhsMod.mPaintFilterSetBits != rhsMod.mPaintFilterSetBits) return false;
+
+ return true;
+ }
+
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) {
+ DEFER_LOGD("%d replaying DrawingBatch %p, with %d ops (batch id %x, merge id %p)",
+ index, this, mOps.size(), getBatchId(), getMergeId());
+ if (mOps.size() == 1) {
+ return DrawBatch::replay(renderer, dirty, false);
+ }
+
+ DrawOp* op = mOps[0];
+ status_t status = op->multiDraw(renderer, dirty, mOps, mBounds);
+ DisplayListLogBuffer& buffer = DisplayListLogBuffer::getInstance();
+ buffer.writeCommand(0, "multiDraw");
+ buffer.writeCommand(1, op->name());
+
+#if DEBUG_MERGE_BEHAVIOR
+ renderer.drawScreenSpaceColorRect(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom,
+ DEBUG_COLOR_MERGEDBATCH);
+#endif
+ return status;
+ }
+};
+
+class StateOpBatch : public Batch {
public:
// creates a single operation batch
StateOpBatch(StateOp* op) : mOp(op) {}
- bool intersects(Rect& rect) {
- // if something checks for intersection, it's trying to go backwards across a state op,
- // something not currently supported - state ops are always barriers
- CRASH();
- return false;
- }
-
- virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) {
DEFER_LOGD("replaying state op batch %p", this);
renderer.restoreDisplayState(mOp->state);
@@ -124,18 +234,11 @@
const StateOp* mOp;
};
-class RestoreToCountBatch : public DrawOpBatch {
+class RestoreToCountBatch : public Batch {
public:
RestoreToCountBatch(StateOp* op, int restoreCount) : mOp(op), mRestoreCount(restoreCount) {}
- bool intersects(Rect& rect) {
- // if something checks for intersection, it's trying to go backwards across a state op,
- // something not currently supported - state ops are always barriers
- CRASH();
- return false;
- }
-
- virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) {
DEFER_LOGD("batch %p restoring to count %d", this, mRestoreCount);
renderer.restoreDisplayState(mOp->state);
@@ -155,14 +258,30 @@
const int mRestoreCount;
};
+#if DEBUG_MERGE_BEHAVIOR
+class BarrierDebugBatch : public Batch {
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int index) {
+ renderer.drawScreenSpaceColorRect(0, 0, 10000, 10000, DEBUG_COLOR_BARRIER);
+ return DrawGlInfo::kStatusDrew;
+ }
+};
+#endif
+
/////////////////////////////////////////////////////////////////////////////////
// DeferredDisplayList
/////////////////////////////////////////////////////////////////////////////////
void DeferredDisplayList::resetBatchingState() {
for (int i = 0; i < kOpBatch_Count; i++) {
- mBatchIndices[i] = -1;
+ mBatchLookup[i] = NULL;
+ mMergingBatches[i].clear();
}
+#if DEBUG_MERGE_BEHAVIOR
+ if (mBatches.size() != 0) {
+ mBatches.add(new BarrierDebugBatch());
+ }
+#endif
+ mEarliestBatchIndex = mBatches.size();
}
void DeferredDisplayList::clear() {
@@ -174,6 +293,7 @@
}
mBatches.clear();
mSaveStack.clear();
+ mEarliestBatchIndex = 0;
}
/////////////////////////////////////////////////////////////////////////////////
@@ -282,28 +402,35 @@
return; // quick rejected
}
- op->onDrawOpDeferred(renderer);
+ int batchId = kOpBatch_None;
+ mergeid_t mergeId = (mergeid_t) -1;
+ bool mergeable = op->onDefer(renderer, &batchId, &mergeId);
+
+ // complex clip has a complex set of expectations on the renderer state - for now, avoid taking
+ // the merge path in those cases
+ mergeable &= !recordingComplexClip();
if (CC_UNLIKELY(renderer.getCaches().drawReorderDisabled)) {
// TODO: elegant way to reuse batches?
- DrawOpBatch* b = new DrawOpBatch();
+ DrawBatch* b = new DrawBatch(batchId, mergeId);
b->add(op);
mBatches.add(b);
return;
}
- // disallowReorder isn't set, so find the latest batch of the new op's type, and try to merge
- // the new op into it
- DrawOpBatch* targetBatch = NULL;
- int batchId = op->getBatchId();
+ // find the latest batch of the new op's type, and try to merge the new op into it
+ DrawBatch* targetBatch = NULL;
+ // insertion point of a new batch, will hopefully be immediately after similar batch
+ // (eventually, should be similar shader)
+ int insertBatchIndex = mBatches.size();
if (!mBatches.isEmpty()) {
if (op->state.mBounds.isEmpty()) {
// don't know the bounds for op, so add to last batch and start from scratch on next op
- mBatches.top()->add(op);
- for (int i = 0; i < kOpBatch_Count; i++) {
- mBatchIndices[i] = -1;
- }
+ DrawBatch* b = new DrawBatch(batchId, mergeId);
+ b->add(op);
+ mBatches.add(b);
+ resetBatchingState();
#if DEBUG_DEFER
DEFER_LOGD("Warning: Encountered op with empty bounds, resetting batches");
op->output(2);
@@ -311,13 +438,36 @@
return;
}
- if (batchId >= 0 && mBatchIndices[batchId] != -1) {
- int targetIndex = mBatchIndices[batchId];
- targetBatch = mBatches[targetIndex];
+ if (mergeable) {
+ // Try to merge with any existing batch with same mergeId.
+ if (mMergingBatches[batchId].get(mergeId, targetBatch)) {
+ if (!((MergingDrawBatch*) targetBatch)->canMergeWith(op)) {
+ targetBatch = NULL;
+ }
+ }
+ } else {
+ // join with similar, non-merging batch
+ targetBatch = (DrawBatch*)mBatchLookup[batchId];
+ }
+
+ if (targetBatch || mergeable) {
// iterate back toward target to see if anything drawn since should overlap the new op
- for (int i = mBatches.size() - 1; i > targetIndex; i--) {
- DrawOpBatch* overBatch = mBatches[i];
+ // if no target, merging ops still interate to find similar batch to insert after
+ for (int i = mBatches.size() - 1; i >= mEarliestBatchIndex; i--) {
+ DrawBatch* overBatch = (DrawBatch*)mBatches[i];
+
+ if (overBatch == targetBatch) break;
+
+ // TODO: also consider shader shared between batch types
+ if (batchId == overBatch->getBatchId()) {
+ insertBatchIndex = i + 1;
+ if (!targetBatch) break; // found insert position, quit
+ }
+
if (overBatch->intersects(op->state.mBounds)) {
+ // NOTE: it may be possible to optimize for special cases where two operations
+ // of the same batch/paint could swap order, such as with a non-mergeable
+ // (clipped) and a mergeable text operation
targetBatch = NULL;
#if DEBUG_DEFER
DEFER_LOGD("op couldn't join batch %d, was intersected by batch %d",
@@ -329,13 +479,21 @@
}
}
}
+
if (!targetBatch) {
- targetBatch = new DrawOpBatch();
- mBatches.add(targetBatch);
- if (batchId >= 0) {
- mBatchIndices[batchId] = mBatches.size() - 1;
+ if (mergeable) {
+ targetBatch = new MergingDrawBatch(batchId, mergeId);
+ mMergingBatches[batchId].put(mergeId, targetBatch);
+ } else {
+ targetBatch = new DrawBatch(batchId, mergeId);
+ mBatchLookup[batchId] = targetBatch;
+ DEFER_LOGD("creating Batch %p, bid %x, at %d",
+ targetBatch, batchId, insertBatchIndex);
}
+
+ mBatches.insertAt(targetBatch, insertBatchIndex);
}
+
targetBatch->add(op);
}
@@ -363,16 +521,14 @@
// Replay / flush
/////////////////////////////////////////////////////////////////////////////////
-static status_t replayBatchList(Vector<DrawOpBatch*>& batchList,
+static status_t replayBatchList(const Vector<Batch*>& batchList,
OpenGLRenderer& renderer, Rect& dirty) {
status_t status = DrawGlInfo::kStatusDone;
- int opCount = 0;
for (unsigned int i = 0; i < batchList.size(); i++) {
- status |= batchList[i]->replay(renderer, dirty);
- opCount += batchList[i]->count();
+ status |= batchList[i]->replay(renderer, dirty, i);
}
- DEFER_LOGD("--flushed, drew %d batches (total %d ops)", batchList.size(), opCount);
+ DEFER_LOGD("--flushed, drew %d batches", batchList.size());
return status;
}
@@ -400,7 +556,6 @@
renderer.setDrawModifiers(restoreDrawModifiers);
DEFER_LOGD("--flush complete, returning %x", status);
-
clear();
return status;
}
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 653f315..9782c1c 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -22,6 +22,9 @@
#include "Matrix.h"
#include "Rect.h"
+#include "utils/TinyHashMap.h"
+
+class SkBitmap;
namespace android {
namespace uirenderer {
@@ -31,16 +34,21 @@
class SaveOp;
class SaveLayerOp;
class StateOp;
-class DrawOpBatch;
class OpenGLRenderer;
+class Batch;
+class DrawBatch;
+class MergingDrawBatch;
+
+typedef void* mergeid_t;
+
class DeferredDisplayList {
public:
DeferredDisplayList() { clear(); }
~DeferredDisplayList() { clear(); }
enum OpBatchId {
- kOpBatch_None = -1, // Don't batch
+ kOpBatch_None = 0, // Don't batch
kOpBatch_Bitmap,
kOpBatch_Patch,
kOpBatch_AlphaVertices,
@@ -96,8 +104,20 @@
Vector<int> mSaveStack;
int mComplexClipStackStart;
- Vector<DrawOpBatch*> mBatches;
- int mBatchIndices[kOpBatch_Count];
+ Vector<Batch*> mBatches;
+
+ // Maps batch ids to the most recent *non-merging* batch of that id
+ Batch* mBatchLookup[kOpBatch_Count];
+
+ // Points to the index after the most recent barrier
+ int mEarliestBatchIndex;
+
+ /**
+ * Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
+ * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
+ * collide, which avoids the need to resolve mergeid collisions.
+ */
+ TinyHashMap<mergeid_t, DrawBatch*> mMergingBatches[kOpBatch_Count];
};
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 36c95f9..26abec2 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -485,7 +485,7 @@
#if DEBUG_DISPLAY_LIST
Rect* clipRect = renderer.getClipRect();
- DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
+ DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.0f, %.0f, %.0f",
level * 2, "", this, mName.string(), clipRect->left, clipRect->top,
clipRect->right, clipRect->bottom);
#endif
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index a5dee9f..ad7edb1 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -121,6 +121,7 @@
};
class DrawOp : public DisplayListOp {
+friend class MergingDrawBatch;
public:
DrawOp(SkPaint* paint)
: mPaint(paint), mQuickRejected(false) {}
@@ -145,12 +146,41 @@
return;
}
- replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty, level);
+ replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) = 0;
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
- virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
+ /**
+ * Draw multiple instances of an operation, must be overidden for operations that merge
+ *
+ * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
+ * and pure translation transformations. Other guarantees of similarity should be enforced by
+ * reducing which operations are tagged as mergeable.
+ */
+ virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
+ const Vector<DrawOp*>& ops, const Rect& bounds) {
+ status_t status = DrawGlInfo::kStatusDone;
+ for (unsigned int i = 0; i < ops.size(); i++) {
+ renderer.restoreDisplayState(ops[i]->state);
+ status |= ops[i]->applyDraw(renderer, dirty);
+ }
+ return status;
+ }
+
+ /*
+ * When this method is invoked the state field is initialized to have the
+ * final rendering state. We can thus use it to process data as it will be
+ * used at draw time.
+ *
+ * Additionally, this method allows subclasses to provide defer-time preferences for batching
+ * and merging.
+ *
+ * Return true if the op can merge with others of its kind (such subclasses should implement
+ * multiDraw)
+ */
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ return false;
}
// returns true if bounds exist
@@ -160,12 +190,11 @@
void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
bool getQuickRejected() { return mQuickRejected; }
- /** Batching disabled by default, turned on for individual ops */
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_None;
+ inline int getPaintAlpha() {
+ return OpenGLRenderer::getAlphaDirect(mPaint);
}
- float strokeWidthOutset() {
+ inline float strokeWidthOutset() {
float width = mPaint->getStrokeWidth();
if (width == 0) return 0.5f; // account for hairline
return width * 0.5f;
@@ -207,6 +236,14 @@
return true;
}
+ bool mergeAllowed() {
+ // checks that we're unclipped, and srcover
+ const Rect& opBounds = state.mBounds;
+ return fabs(opBounds.getWidth() - mLocalBounds.getWidth()) < 0.1 &&
+ fabs(opBounds.getHeight() - mLocalBounds.getHeight()) < 0.1 &&
+ (OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode);
+ }
+
protected:
Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
};
@@ -686,20 +723,58 @@
paint),
mBitmap(bitmap) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
getPaint(renderer));
}
+#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
+ TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
+ texCoordsRect.xDim, texCoordsRect.yDim)
+
+ virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
+ const Vector<DrawOp*>& ops, const Rect& bounds) {
+ renderer.restoreDisplayState(state, true); // restore all but the clip
+ renderer.setFullScreenClip(); // ensure merged ops aren't clipped
+ TextureVertex vertices[6 * ops.size()];
+ TextureVertex* vertex = &vertices[0];
+
+ // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op, and allowing
+ // them to be merged in getBatchId()
+ const Rect texCoords(0, 0, 1, 1);
+
+ const float width = mBitmap->width();
+ const float height = mBitmap->height();
+ for (unsigned int i = 0; i < ops.size(); i++) {
+ const Rect& opBounds = ops[i]->state.mBounds;
+ SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
+ SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
+ SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
+
+ SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
+ SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
+ SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
+ }
+
+ return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], bounds, mPaint);
+ }
+
virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
}
virtual const char* name() { return "DrawBitmap"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_Bitmap;
+
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ *batchId = DeferredDisplayList::kOpBatch_Bitmap;
+ *mergeId = (mergeid_t)mBitmap;
+
+ // don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
+ // MergingDrawBatch::canMergeWith
+ return mergeAllowed() && (mBitmap->getConfig() != SkBitmap::kA8_Config);
}
+ const SkBitmap* bitmap() { return mBitmap; }
protected:
SkBitmap* mBitmap;
};
@@ -713,7 +788,7 @@
transform.mapRect(mLocalBounds);
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
}
@@ -721,9 +796,11 @@
OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
}
- virtual const char* name() { return "DrawBitmap"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_Bitmap;
+ virtual const char* name() { return "DrawBitmapMatrix"; }
+
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ *batchId = DeferredDisplayList::kOpBatch_Bitmap;
+ return false;
}
private:
@@ -738,7 +815,7 @@
: DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
getPaint(renderer));
@@ -750,8 +827,10 @@
}
virtual const char* name() { return "DrawBitmapRect"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_Bitmap;
+
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ *batchId = DeferredDisplayList::kOpBatch_Bitmap;
+ return false;
}
private:
@@ -764,7 +843,7 @@
DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
: DrawBitmapOp(bitmap, left, top, paint) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
mLocalBounds.top, getPaint(renderer));
}
@@ -774,8 +853,10 @@
}
virtual const char* name() { return "DrawBitmapData"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_Bitmap;
+
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ *batchId = DeferredDisplayList::kOpBatch_Bitmap;
+ return false;
}
};
@@ -787,7 +868,7 @@
mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
mVertices(vertices), mColors(colors) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
mVertices, mColors, getPaint(renderer));
}
@@ -797,8 +878,10 @@
}
virtual const char* name() { return "DrawBitmapMesh"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_Bitmap;
+
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ *batchId = DeferredDisplayList::kOpBatch_Bitmap;
+ return false;
}
private:
@@ -820,7 +903,7 @@
mColors(colors), mxDivsCount(width), myDivsCount(height),
mNumColors(numColors), mAlpha(alpha), mMode(mode) {};
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
// NOTE: not calling the virtual method, which takes a paint
return renderer.drawPatch(mBitmap, mxDivs, myDivs, mColors,
mxDivsCount, myDivsCount, mNumColors,
@@ -833,8 +916,11 @@
}
virtual const char* name() { return "DrawPatch"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_Patch;
+
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ *batchId = DeferredDisplayList::kOpBatch_Patch;
+ *mergeId = (mergeid_t)mBitmap;
+ return true;
}
private:
@@ -854,7 +940,7 @@
DrawColorOp(int color, SkXfermode::Mode mode)
: DrawOp(0), mColor(color), mMode(mode) {};
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawColor(mColor, mMode);
}
@@ -882,13 +968,15 @@
return true;
}
- virtual DeferredDisplayList::OpBatchId getBatchId() {
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
if (mPaint->getPathEffect()) {
- return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
+ *batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
+ } else {
+ *batchId = mPaint->isAntiAlias() ?
+ DeferredDisplayList::kOpBatch_AlphaVertices :
+ DeferredDisplayList::kOpBatch_Vertices;
}
- return mPaint->isAntiAlias() ?
- DeferredDisplayList::kOpBatch_AlphaVertices :
- DeferredDisplayList::kOpBatch_Vertices;
+ return false;
}
};
@@ -897,7 +985,7 @@
DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
: DrawStrokableOp(left, top, right, bottom, paint) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
}
@@ -915,7 +1003,7 @@
: DrawBoundedOp(rects, count, paint),
mRects(rects), mCount(count) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawRects(mRects, mCount, getPaint(renderer));
}
@@ -925,8 +1013,9 @@
virtual const char* name() { return "DrawRects"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_Vertices;
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ *batchId = DeferredDisplayList::kOpBatch_Vertices;
+ return false;
}
private:
@@ -940,7 +1029,7 @@
float rx, float ry, SkPaint* paint)
: DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
}
@@ -962,7 +1051,7 @@
: DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
mX(x), mY(y), mRadius(radius) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
}
@@ -983,7 +1072,7 @@
DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
: DrawStrokableOp(left, top, right, bottom, paint) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
}
@@ -1002,7 +1091,7 @@
: DrawStrokableOp(left, top, right, bottom, paint),
mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
mLocalBounds.right, mLocalBounds.bottom,
mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
@@ -1033,13 +1122,16 @@
mLocalBounds.set(left, top, left + width, top + height);
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawPath(mPath, getPaint(renderer));
}
- virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
SkPaint* paint = getPaint(renderer);
renderer.getCaches().pathCache.precache(mPath, paint);
+
+ *batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
+ return false;
}
virtual void output(int level, uint32_t logFlags) {
@@ -1048,9 +1140,6 @@
virtual const char* name() { return "DrawPath"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
- }
private:
SkPath* mPath;
};
@@ -1063,7 +1152,7 @@
mLocalBounds.outset(strokeWidthOutset());
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawLines(mPoints, mCount, getPaint(renderer));
}
@@ -1073,10 +1162,11 @@
virtual const char* name() { return "DrawLines"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return mPaint->isAntiAlias() ?
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
+ *batchId = mPaint->isAntiAlias() ?
DeferredDisplayList::kOpBatch_AlphaVertices :
DeferredDisplayList::kOpBatch_Vertices;
+ return false;
}
protected:
@@ -1089,7 +1179,7 @@
DrawPointsOp(float* points, int count, SkPaint* paint)
: DrawLinesOp(points, count, paint) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
}
@@ -1109,17 +1199,18 @@
OP_LOG("Draw some text, %d bytes", mBytesCount);
}
- virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
SkPaint* paint = getPaint(renderer);
FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
fontRenderer.precache(paint, mText, mCount, mat4::identity());
- }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return mPaint->getColor() == 0xff000000 ?
+ *batchId = mPaint->getColor() == 0xff000000 ?
DeferredDisplayList::kOpBatch_Text :
DeferredDisplayList::kOpBatch_ColorText;
+
+ return false;
}
+
protected:
const char* mText;
int mBytesCount;
@@ -1135,7 +1226,7 @@
/* TODO: inherit from DrawBounded and init mLocalBounds */
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
mHOffset, mVOffset, getPaint(renderer));
}
@@ -1156,7 +1247,7 @@
/* TODO: inherit from DrawBounded and init mLocalBounds */
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
}
@@ -1189,12 +1280,7 @@
memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
}
- /*
- * When this method is invoked the state field is initialized to have the
- * final rendering state. We can thus use it to process data as it will be
- * used at draw time.
- */
- virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
+ virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
SkPaint* paint = getPaint(renderer);
FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
@@ -1202,25 +1288,44 @@
fontRenderer.precache(paint, mText, mCount, transform);
mPrecacheTransform = transform;
}
+ *batchId = mPaint->getColor() == 0xff000000 ?
+ DeferredDisplayList::kOpBatch_Text :
+ DeferredDisplayList::kOpBatch_ColorText;
+
+ *mergeId = (mergeid_t)mPaint->getColor();
+
+ // don't merge decorated text - the decorations won't draw in order
+ bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
+ SkPaint::kStrikeThruText_Flag));
+ return mergeAllowed() && noDecorations;
}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
mPositions, getPaint(renderer), mLength);
}
+ virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
+ const Vector<DrawOp*>& ops, const Rect& bounds) {
+ status_t status = DrawGlInfo::kStatusDone;
+ renderer.setFullScreenClip(); // ensure merged ops aren't clipped
+ for (unsigned int i = 0; i < ops.size(); i++) {
+ DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
+ renderer.restoreDisplayState(ops[i]->state, true); // restore all but the clip
+
+ DrawTextOp& op = *((DrawTextOp*)ops[i]);
+ status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
+ op.mPositions, op.getPaint(renderer), op.mLength, drawOpMode);
+ }
+ return status;
+ }
+
virtual void output(int level, uint32_t logFlags) {
OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
}
virtual const char* name() { return "DrawText"; }
- virtual DeferredDisplayList::OpBatchId getBatchId() {
- return mPaint->getColor() == 0xff000000 ?
- DeferredDisplayList::kOpBatch_Text :
- DeferredDisplayList::kOpBatch_ColorText;
- }
-
private:
const char* mText;
int mBytesCount;
@@ -1241,7 +1346,7 @@
DrawFunctorOp(Functor* functor)
: DrawOp(0), mFunctor(functor) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
renderer.startMark("GL functor");
status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
renderer.endMark();
@@ -1269,14 +1374,14 @@
mDisplayList->defer(deferStruct, level + 1);
}
}
-virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) {
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) {
if (mDisplayList && mDisplayList->isRenderable()) {
mDisplayList->replay(replayStruct, level + 1);
}
}
// NOT USED since replay() is overridden
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return DrawGlInfo::kStatusDone;
}
@@ -1299,7 +1404,7 @@
DrawLayerOp(Layer* layer, float x, float y)
: DrawOp(0), mLayer(layer), mX(x), mY(y) {}
- virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
return renderer.drawLayer(mLayer, mX, mY);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 0b8f7e6..876c38a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -276,6 +276,15 @@
bitmap = refBitmap(bitmap);
paint = refPaint(paint);
+ if (srcLeft == 0 && srcTop == 0 &&
+ srcRight == bitmap->width() && srcBottom == bitmap->height() &&
+ (srcBottom - srcTop == dstBottom - dstTop) &&
+ (srcRight - srcLeft == dstRight - dstLeft)) {
+ // transform simple rect to rect drawing case into position bitmap ops, since they merge
+ addDrawOp(new (alloc()) DrawBitmapOp(bitmap, dstLeft, dstTop, paint));
+ return DrawGlInfo::kStatusDone;
+ }
+
addDrawOp(new (alloc()) DrawBitmapRectOp(bitmap,
srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, paint));
@@ -413,7 +422,9 @@
}
status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
- float x, float y, const float* positions, SkPaint* paint, float length) {
+ float x, float y, const float* positions, SkPaint* paint,
+ float length, DrawOpMode drawOpMode) {
+
if (!text || count <= 0) return DrawGlInfo::kStatusDone;
if (length < 0.0f) length = paint->measureText(text, bytesCount);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 19f7eb6..75abad6 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -121,8 +121,9 @@
float hOffset, float vOffset, SkPaint* paint);
virtual status_t drawPosText(const char* text, int bytesCount, int count,
const float* positions, SkPaint* paint);
- virtual status_t drawText(const char* text, int bytesCount, int count,
- float x, float y, const float* positions, SkPaint* paint, float length);
+ virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
+ const float* positions, SkPaint* paint, float length, DrawOpMode drawOpMode);
+
virtual status_t drawRects(const float* rects, int count, SkPaint* paint);
virtual void resetShader();
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 6894ef9..543cfa2 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -57,7 +57,6 @@
mGammaTable = NULL;
mInitialized = false;
- mMaxNumberOfQuads = 1024;
mCurrentCacheTexture = NULL;
@@ -293,7 +292,7 @@
}
CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool allocate) {
- CacheTexture* cacheTexture = new CacheTexture(width, height, mMaxNumberOfQuads);
+ CacheTexture* cacheTexture = new CacheTexture(width, height, gMaxNumberOfQuads);
if (allocate) {
Caches::getInstance().activeTexture(0);
@@ -320,12 +319,12 @@
// Avoid having to reallocate memory and render quad by quad
void FontRenderer::initVertexArrayBuffers() {
- uint32_t numIndices = mMaxNumberOfQuads * 6;
+ uint32_t numIndices = gMaxNumberOfQuads * 6;
uint32_t indexBufferSizeBytes = numIndices * sizeof(uint16_t);
uint16_t* indexBufferData = (uint16_t*) malloc(indexBufferSizeBytes);
// Four verts, two triangles , six indices per quad
- for (uint32_t i = 0; i < mMaxNumberOfQuads; i++) {
+ for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) {
int i6 = i * 6;
int i4 = i * 4;
@@ -594,7 +593,7 @@
bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text,
uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
- const float* positions, Rect* bounds, Functor* functor) {
+ const float* positions, Rect* bounds, Functor* functor, bool forceFinish) {
if (!mCurrentFont) {
ALOGE("No font set");
return false;
@@ -602,7 +601,10 @@
initRender(clip, bounds, functor);
mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions);
- finishRender();
+
+ if (forceFinish) {
+ finishRender();
+ }
return mDrawn;
}
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 348b7e3..307a1d9 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -66,7 +66,8 @@
// bounds is an out parameter
bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds,
- Functor* functor);
+ Functor* functor, bool forceFinish = true);
+
// bounds is an out parameter
bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds);
@@ -101,6 +102,8 @@
private:
friend class Font;
+ static const uint32_t gMaxNumberOfQuads = 2048;
+
const uint8_t* mGammaTable;
void allocateTextureMemory(CacheTexture* cacheTexture);
@@ -154,7 +157,6 @@
bool mUploadTexture;
- uint32_t mMaxNumberOfQuads;
uint32_t mIndexBufferID;
Functor* mFunctor;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index dcd1eb8..f81b4ff 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -112,11 +112,9 @@
OpenGLRenderer::OpenGLRenderer():
mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
- mDrawModifiers.mShader = NULL;
- mDrawModifiers.mColorFilter = NULL;
+ // *set* draw modifiers to be 0
+ memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
mDrawModifiers.mOverrideLayerAlpha = 1.0f;
- mDrawModifiers.mHasShadow = false;
- mDrawModifiers.mHasDrawFilter = false;
memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
@@ -1330,10 +1328,9 @@
}
}
- if (stateDeferFlags & kStateDeferFlag_Clip) {
+ state.mClipValid = (stateDeferFlags & kStateDeferFlag_Clip);
+ if (state.mClipValid) {
state.mClip.set(currentClip);
- } else {
- state.mClip.setEmpty();
}
// Transform, drawModifiers, and alpha always deferred, since they are used by state operations
@@ -1344,17 +1341,22 @@
return false;
}
-void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state) {
+void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) {
currentTransform().load(state.mMatrix);
mDrawModifiers = state.mDrawModifiers;
mSnapshot->alpha = state.mAlpha;
- if (!state.mClip.isEmpty()) {
+ if (state.mClipValid && !skipClipRestore) {
mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom);
dirtyClip();
}
}
+void OpenGLRenderer::setFullScreenClip() {
+ mSnapshot->setClip(0, 0, mWidth, mHeight);
+ dirtyClip();
+}
+
///////////////////////////////////////////////////////////////////////////////
// Transforms
///////////////////////////////////////////////////////////////////////////////
@@ -1963,6 +1965,42 @@
(GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
}
+status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices,
+ const Rect& bounds, SkPaint* paint) {
+
+ // merged draw operations don't need scissor, but clip should still be valid
+ mCaches.setScissorEnabled(mScissorOptimizationDisabled);
+
+ mCaches.activeTexture(0);
+ Texture* texture = mCaches.textureCache.get(bitmap);
+ if (!texture) return DrawGlInfo::kStatusDone;
+ const AutoTexture autoCleanup(texture);
+
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
+ texture->setWrap(GL_CLAMP_TO_EDGE, true);
+ texture->setFilter(GL_NEAREST, true); // merged ops are always pure-translation for now
+
+ const float x = (int) floorf(bounds.left + 0.5f);
+ const float y = (int) floorf(bounds.top + 0.5f);
+ if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) {
+ int color = paint != NULL ? paint->getColor() : 0;
+ drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
+ texture->id, paint != NULL, color, alpha, mode,
+ &vertices[0].position[0], &vertices[0].texture[0],
+ GL_TRIANGLES, bitmapCount * 6, true, true);
+ } else {
+ drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
+ texture->id, alpha / 255.0f, mode, texture->blend,
+ &vertices[0].position[0], &vertices[0].texture[0],
+ GL_TRIANGLES, bitmapCount * 6, false, true, 0, true);
+ }
+
+ return DrawGlInfo::kStatusDrew;
+}
+
status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
const float right = left + bitmap->width();
const float bottom = top + bitmap->height();
@@ -2796,8 +2834,11 @@
}
status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
- float x, float y, const float* positions, SkPaint* paint, float length) {
- if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
+ float x, float y, const float* positions, SkPaint* paint, float length,
+ DrawOpMode drawOpMode) {
+
+ if (drawOpMode == kDrawOpMode_Immediate &&
+ (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint))) {
return DrawGlInfo::kStatusDone;
}
@@ -2815,8 +2856,13 @@
SkPaint::FontMetrics metrics;
paint->getFontMetrics(&metrics, 0.0f);
- if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) {
- return DrawGlInfo::kStatusDone;
+ if (drawOpMode == kDrawOpMode_Immediate) {
+ if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) {
+ return DrawGlInfo::kStatusDone;
+ }
+ } else {
+ // merged draw operations don't need scissor, but clip should still be valid
+ mCaches.setScissorEnabled(mScissorOptimizationDisabled);
}
const float oldX = x;
@@ -2868,17 +2914,20 @@
bool status;
TextSetupFunctor functor(*this, x, y, pureTranslate, alpha, mode, paint);
+
+ // don't call issuedrawcommand, do it at end of batch
+ bool forceFinish = (drawOpMode != kDrawOpMode_Defer);
if (CC_UNLIKELY(paint->getTextAlign() != SkPaint::kLeft_Align)) {
SkPaint paintCopy(*paint);
paintCopy.setTextAlign(SkPaint::kLeft_Align);
status = fontRenderer.renderPosText(&paintCopy, clip, text, 0, bytesCount, count, x, y,
- positions, hasActiveLayer ? &bounds : NULL, &functor);
+ positions, hasActiveLayer ? &bounds : NULL, &functor, forceFinish);
} else {
status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
- positions, hasActiveLayer ? &bounds : NULL, &functor);
+ positions, hasActiveLayer ? &bounds : NULL, &functor, forceFinish);
}
- if (status && hasActiveLayer) {
+ if ((status || drawOpMode != kDrawOpMode_Immediate) && hasActiveLayer) {
if (!pureTranslate) {
transform.mapRect(bounds);
}
@@ -3093,7 +3142,11 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::resetPaintFilter() {
+ // when clearing the PaintFilter, the masks should also be cleared for simple DrawModifier
+ // comparison, see MergingDrawBatch::canMergeWith
mDrawModifiers.mHasDrawFilter = false;
+ mDrawModifiers.mPaintFilterClearBits = 0;
+ mDrawModifiers.mPaintFilterSetBits = 0;
}
void OpenGLRenderer::setupPaintFilter(int clearBits, int setBits) {
@@ -3365,7 +3418,7 @@
void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
GLuint texture, bool hasColor, int color, int alpha, SkXfermode::Mode mode,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
- bool ignoreTransform, bool dirty) {
+ bool ignoreTransform, bool ignoreScale, bool dirty) {
setupDraw();
setupDrawWithTexture(true);
@@ -3377,7 +3430,11 @@
setupDrawBlending(true, mode);
setupDrawProgram();
if (!dirty) setupDrawDirtyRegionsDisabled();
- setupDrawModelView(left, top, right, bottom, ignoreTransform);
+ if (!ignoreScale) {
+ setupDrawModelView(left, top, right, bottom, ignoreTransform);
+ } else {
+ setupDrawModelViewTranslate(left, top, right, bottom, ignoreTransform);
+ }
setupDrawTexture(texture);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index dd7a5a2..a0ad888 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -71,10 +71,17 @@
kStateDeferFlag_Clip = 0x2
};
+enum DrawOpMode {
+ kDrawOpMode_Immediate,
+ kDrawOpMode_Defer,
+ kDrawOpMode_Flush
+};
+
struct DeferredDisplayState {
- Rect mBounds; // local bounds, mapped with matrix to be in screen space coordinates, clipped.
+ Rect mBounds; // global op bounds, mapped by mMatrix to be in screen space coordinates, clipped.
// the below are set and used by the OpenGLRenderer at record and deferred playback
+ bool mClipValid;
Rect mClip;
mat4 mMatrix;
DrawModifiers mDrawModifiers;
@@ -232,6 +239,8 @@
virtual void outputDisplayList(DisplayList* displayList);
virtual status_t drawLayer(Layer* layer, float x, float y);
virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
+ status_t drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices,
+ const Rect& bounds, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
@@ -261,7 +270,8 @@
virtual status_t drawPosText(const char* text, int bytesCount, int count,
const float* positions, SkPaint* paint);
virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
- const float* positions, SkPaint* paint, float length = -1.0f);
+ const float* positions, SkPaint* paint, float length = -1.0f,
+ DrawOpMode drawOpMode = kDrawOpMode_Immediate);
virtual status_t drawRects(const float* rects, int count, SkPaint* paint);
virtual void resetShader();
@@ -282,7 +292,8 @@
SkPaint* filterPaint(SkPaint* paint);
bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
- void restoreDisplayState(const DeferredDisplayState& state);
+ void restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore = false);
+ void setFullScreenClip();
const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
@@ -336,20 +347,18 @@
* @param mode Where to store the resulting xfermode
*/
static inline void getAlphaAndModeDirect(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
- if (paint) {
- *mode = getXfermode(paint->getXfermode());
+ *mode = getXfermodeDirect(paint);
+ *alpha = getAlphaDirect(paint);
+ }
- // Skia draws using the color's alpha channel if < 255
- // Otherwise, it uses the paint's alpha
- int color = paint->getColor();
- *alpha = (color >> 24) & 0xFF;
- if (*alpha == 255) {
- *alpha = paint->getAlpha();
- }
- } else {
- *mode = SkXfermode::kSrcOver_Mode;
- *alpha = 255;
- }
+ static inline SkXfermode::Mode getXfermodeDirect(SkPaint* paint) {
+ if (!paint) return SkXfermode::kSrcOver_Mode;
+ return getXfermode(paint->getXfermode());
+ }
+
+ static inline int getAlphaDirect(SkPaint* paint) {
+ if (!paint) return 255;
+ return paint->getAlpha();
}
/**
@@ -358,6 +367,20 @@
*/
mat4 findBestFontTransform(const mat4& transform) const;
+#if DEBUG_MERGE_BEHAVIOR
+ void drawScreenSpaceColorRect(float left, float top, float right, float bottom, int color) {
+ mCaches.setScissorEnabled(false);
+
+ // should only be called outside of other draw ops, so stencil can only be in test state
+ bool stencilWasEnabled = mCaches.stencil.isTestEnabled();
+ mCaches.stencil.disable();
+
+ drawColorRect(left, top, right, bottom, color, SkXfermode::kSrcOver_Mode, true);
+
+ if (stencilWasEnabled) mCaches.stencil.enableTest();
+ }
+#endif
+
protected:
/**
* Computes the projection matrix, initialize the first snapshot
@@ -778,7 +801,7 @@
void drawAlpha8TextureMesh(float left, float top, float right, float bottom,
GLuint texture, bool hasColor, int color, int alpha, SkXfermode::Mode mode,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
- bool ignoreTransform, bool dirty = true);
+ bool ignoreTransform, bool ignoreScale = false, bool dirty = true);
/**
* Draws text underline and strike-through if needed.
diff --git a/libs/hwui/utils/TinyHashMap.h b/libs/hwui/utils/TinyHashMap.h
new file mode 100644
index 0000000..8855140
--- /dev/null
+++ b/libs/hwui/utils/TinyHashMap.h
@@ -0,0 +1,72 @@
+/*
+ * 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_TINYHASHMAP_H
+#define ANDROID_HWUI_TINYHASHMAP_H
+
+#include <utils/BasicHashtable.h>
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * A very simple hash map that doesn't allow duplicate keys, overwriting the older entry.
+ *
+ * Currently, expects simple keys that are handled by hash_t()
+ */
+template <typename TKey, typename TValue>
+class TinyHashMap {
+public:
+ typedef key_value_pair_t<TKey, TValue> TEntry;
+
+ /**
+ * Puts an entry in the hash, removing any existing entry with the same key
+ */
+ void put(TKey key, TValue value) {
+ hash_t hash = hash_t(key);
+
+ ssize_t index = mTable.find(-1, hash, key);
+ if (index != -1) {
+ mTable.removeAt(index);
+ }
+
+ TEntry initEntry(key, value);
+ mTable.add(hash, initEntry);
+ }
+
+ /**
+ * Return true if key is in the map, in which case stores the value in the output ref
+ */
+ bool get(TKey key, TValue& outValue) {
+ hash_t hash = hash_t(key);
+ ssize_t index = mTable.find(-1, hash, key);
+ if (index == -1) {
+ return false;
+ }
+ outValue = mTable.entryAt(index).value;
+ return true;
+ }
+
+ void clear() { mTable.clear(); }
+
+private:
+ BasicHashtable<TKey, TEntry> mTable;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_TINYHASHMAP_H
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 4eb0c56..6872278 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -215,6 +215,7 @@
public static final int MEDIA_DRM_KEY_TYPE_STREAMING = 1;
public static final int MEDIA_DRM_KEY_TYPE_OFFLINE = 2;
+ public static final int MEDIA_DRM_KEY_TYPE_RELEASE = 3;
public final class KeyRequest {
public KeyRequest() {}
@@ -223,28 +224,36 @@
};
/**
- * A key request/response exchange occurs between the app and a license
- * server to obtain the keys to decrypt encrypted content. getKeyRequest()
- * is used to obtain an opaque key request byte array that is delivered to the
- * license server. The opaque key request byte array is returned in
- * KeyRequest.data. The recommended URL to deliver the key request to is
+ * A key request/response exchange occurs between the app and a license server
+ * to obtain or release keys used to decrypt encrypted content.
+ * getKeyRequest() is used to obtain an opaque key request byte array that is
+ * delivered to the license server. The opaque key request byte array is returned
+ * in KeyRequest.data. The recommended URL to deliver the key request to is
* returned in KeyRequest.defaultUrl.
*
* After the app has received the key request response from the server,
* it should deliver to the response to the DRM engine plugin using the method
* {@link #provideKeyResponse}.
*
- * @param sessonId the session ID for the drm session
+ * @param scope may be a sessionId or a keySetId, depending on the specified keyType.
+ * When the keyType is MEDIA_DRM_KEY_TYPE_STREAMING or MEDIA_DRM_KEY_TYPE_OFFLINE,
+ * scope should be set to the sessionId the keys will be provided to. When the keyType
+ * is MEDIA_DRM_KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys
+ * being released. Releasing keys from a device invalidates them for all sessions.
* @param init container-specific data, its meaning is interpreted based on the
* mime type provided in the mimeType parameter. It could contain, for example,
* the content ID, key ID or other data obtained from the content metadata that is
- * required in generating the key request.
+ * required in generating the key request. init may be null when keyType is
+ * MEDIA_DRM_KEY_TYPE_RELEASE.
* @param mimeType identifies the mime type of the content
- * @param keyType specifes if the request is for streaming or offline content
+ * @param keyType specifes the type of the request. The request may be to acquire
+ * keys for streaming or offline content, or to release previously acquired
+ * keys, which are identified by a keySetId.
+
* @param optionalParameters are included in the key request message to
* allow a client application to provide additional message parameters to the server.
*/
- public native KeyRequest getKeyRequest(byte[] sessionId, byte[] init,
+ public native KeyRequest getKeyRequest(byte[] scope, byte[] init,
String mimeType, int keyType,
HashMap<String, String> optionalParameters)
throws MediaDrmException;
@@ -272,13 +281,11 @@
throws MediaDrmException;
/**
- * Remove the persisted keys associated with an offline license. Keys are persisted
- * when {@link provideKeyResponse} is called with keys obtained from the method
- * {@link getKeyRequest} using keyType = MEDIA_DRM_KEY_TYPE_OFFLINE.
+ * Remove the current keys from a session.
*
- * @param keySetId identifies the saved key set to remove
+ * @param sessionId the session ID for the DRM session
*/
- public native void removeKeys(byte[] keySetId) throws MediaDrmException;
+ public native void removeKeys(byte[] sessionId) throws MediaDrmException;
/**
* Request an informative description of the key status for the session. The status is
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
index 965e378..7315aad 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
@@ -151,7 +151,9 @@
public void onResume(int reason) {
if (DEBUG) Log.d(TAG, "onResume()");
mIsShowing = KeyguardUpdateMonitor.getInstance(mContext).isKeyguardVisible();
- maybeStartBiometricUnlock();
+ if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) {
+ maybeStartBiometricUnlock();
+ }
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
// Registers a callback which handles stopping the biometric unlock and restarting it in
@@ -269,6 +271,14 @@
}
@Override
+ public void onUserSwitchComplete(int userId) {
+ if (DEBUG) Log.d(TAG, "onUserSwitchComplete(" + userId + ")");
+ if (mBiometricUnlock != null) {
+ maybeStartBiometricUnlock();
+ }
+ }
+
+ @Override
public void onKeyguardVisibilityChanged(boolean showing) {
if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
boolean wasShowing = false;
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
index ad87a4b..986dc49 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
@@ -124,6 +124,8 @@
mCallbacks = Lists.newArrayList();
private ContentObserver mDeviceProvisionedObserver;
+ private boolean mSwitchingUser;
+
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -461,11 +463,13 @@
public void onUserSwitching(int newUserId, IRemoteCallback reply) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
newUserId, 0, reply));
+ mSwitchingUser = true;
}
@Override
public void onUserSwitchComplete(int newUserId) throws RemoteException {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
newUserId));
+ mSwitchingUser = false;
}
});
} catch (RemoteException e) {
@@ -529,7 +533,6 @@
cb.onUserSwitching(userId);
}
}
- setAlternateUnlockEnabled(false);
try {
reply.sendResult(null);
} catch (RemoteException e) {
@@ -733,6 +736,10 @@
return mKeyguardIsVisible;
}
+ public boolean isSwitchingUser() {
+ return mSwitchingUser;
+ }
+
private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
final boolean nowPluggedIn = current.isPluggedIn();
final boolean wasPluggedIn = old.isPluggedIn();
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index c49228e..08a95a6 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -319,8 +319,9 @@
mSwitchingUser = true;
resetStateLocked(null);
adjustStatusBarLocked();
- // Disable face unlock when the user switches.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
+ // When we switch users we want to bring the new user to the biometric unlock even
+ // if the current user has gone to the backup.
+ KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
}
}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0619b88..128a49f 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1817,11 +1817,13 @@
addServiceLocked(this, userState);
if (userState.mBindingServices.contains(mComponentName)) {
userState.mBindingServices.remove(mComponentName);
- onUserStateChangedLocked(userState);
try {
- mServiceInterface.setConnection(this, mId);
+ mServiceInterface.setConnection(this, mId);
+ onUserStateChangedLocked(userState);
} catch (RemoteException re) {
- Slog.w(LOG_TAG, "Error while setting connection for service: " + service, re);
+ Slog.w(LOG_TAG, "Error while setting connection for service: "
+ + service, re);
+ binderDied();
}
} else {
binderDied();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index f73a13c..4e7497c 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -19,17 +19,12 @@
import android.os.Parcelable;
import android.os.Process;
import android.security.Credentials;
+import android.security.KeyStore;
import android.text.TextUtils;
-import com.android.org.bouncycastle.asn1.ASN1InputStream;
-import com.android.org.bouncycastle.asn1.ASN1Sequence;
-import com.android.org.bouncycastle.asn1.DEROctetString;
-import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
-
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.KeyFactory;
-import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
@@ -481,7 +476,8 @@
String caCertName = Credentials.CA_CERTIFICATE + name;
if (mClientCertificate != null) {
byte[] privKeyData = mClientPrivateKey.getEncoded();
- ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID);
+ ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
+ KeyStore.FLAG_ENCRYPTED);
if (ret == false) {
return ret;
}
@@ -525,7 +521,7 @@
Certificate cert) {
try {
byte[] certData = Credentials.convertToPem(cert);
- return keyStore.put(name, certData, Process.WIFI_UID);
+ return keyStore.put(name, certData, Process.WIFI_UID, KeyStore.FLAG_ENCRYPTED);
} catch (IOException e1) {
return false;
} catch (CertificateException e2) {
@@ -533,7 +529,7 @@
}
}
- void removeKeys(android.security.KeyStore keyStore) {
+ void removeKeys(KeyStore keyStore) {
String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
// a valid client certificate is configured
if (!TextUtils.isEmpty(client)) {