Merge "System bar tweaks" into honeycomb
diff --git a/api/10.xml b/api/10.xml
index ad54650..e10b357 100644
--- a/api/10.xml
+++ b/api/10.xml
@@ -100906,7 +100906,7 @@
visibility="public"
>
</field>
-<field name="ACTION_TECHNOLOGY_DISCOVERED"
+<field name="ACTION_TECH_DISCOVERED"
type="java.lang.String"
transient="false"
volatile="false"
@@ -100975,29 +100975,12 @@
extends="java.lang.Object"
abstract="false"
static="false"
- final="false"
+ final="true"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.os.Parcelable">
</implements>
-<method name="createMockTag"
- return="android.nfc.Tag"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="byte[]">
-</parameter>
-<parameter name="techList" type="int[]">
-</parameter>
-<parameter name="techListExtras" type="android.os.Bundle[]">
-</parameter>
-</method>
<method name="describeContents"
return="int"
abstract="false"
@@ -101145,19 +101128,6 @@
visibility="public"
>
</method>
-<method name="reconnect"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
</class>
<class name="IsoDep"
extends="android.nfc.tech.BasicTagTechnology"
@@ -101745,7 +101715,7 @@
deprecated="not deprecated"
visibility="public"
>
-<method name="canMakeReadonly"
+<method name="canMakeReadOnly"
return="boolean"
abstract="false"
native="false"
@@ -101807,7 +101777,7 @@
</exception>
</method>
<method name="getType"
- return="int"
+ return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
@@ -101828,7 +101798,7 @@
visibility="public"
>
</method>
-<method name="makeReadonly"
+<method name="makeReadOnly"
return="boolean"
abstract="false"
native="false"
@@ -101859,10 +101829,10 @@
</exception>
</method>
<field name="MIFARE_CLASSIC"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="101"
+ value=""com.nxp.ndef.mifareclassic""
static="true"
final="true"
deprecated="not deprecated"
@@ -101870,10 +101840,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_1"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="1"
+ value=""org.nfcforum.ndef.type1""
static="true"
final="true"
deprecated="not deprecated"
@@ -101881,10 +101851,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_2"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="2"
+ value=""org.nfcforum.ndef.type2""
static="true"
final="true"
deprecated="not deprecated"
@@ -101892,10 +101862,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_3"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="3"
+ value=""org.nfcforum.ndef.type3""
static="true"
final="true"
deprecated="not deprecated"
@@ -101903,21 +101873,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_4"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="OTHER"
- type="int"
- transient="false"
- volatile="false"
- value="-1"
+ value=""org.nfcforum.ndef.type4""
static="true"
final="true"
deprecated="not deprecated"
@@ -101950,6 +101909,23 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
+<method name="formatReadOnly"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="firstMessage" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
<method name="get"
return="android.nfc.tech.NdefFormatable"
abstract="false"
@@ -102246,8 +102222,8 @@
visibility="public"
>
</method>
-<method name="reconnect"
- return="void"
+<method name="isConnected"
+ return="boolean"
abstract="true"
native="false"
synchronized="false"
@@ -102256,8 +102232,6 @@
deprecated="not deprecated"
visibility="public"
>
-<exception name="IOException" type="java.io.IOException">
-</exception>
</method>
</interface>
</package>
diff --git a/api/11.xml b/api/11.xml
index 16984b5..291d8dbd 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -29418,6 +29418,17 @@
<parameter name="uri" type="android.net.Uri">
</parameter>
</method>
+<method name="setDownloadToBeOtaUpdate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="setMimeType"
return="android.app.DownloadManager.Request"
abstract="false"
@@ -118639,7 +118650,7 @@
visibility="public"
>
</field>
-<field name="ACTION_TECHNOLOGY_DISCOVERED"
+<field name="ACTION_TECH_DISCOVERED"
type="java.lang.String"
transient="false"
volatile="false"
@@ -118708,29 +118719,12 @@
extends="java.lang.Object"
abstract="false"
static="false"
- final="false"
+ final="true"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.os.Parcelable">
</implements>
-<method name="createMockTag"
- return="android.nfc.Tag"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="byte[]">
-</parameter>
-<parameter name="techList" type="int[]">
-</parameter>
-<parameter name="techListExtras" type="android.os.Bundle[]">
-</parameter>
-</method>
<method name="describeContents"
return="int"
abstract="false"
@@ -118878,19 +118872,6 @@
visibility="public"
>
</method>
-<method name="reconnect"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
</class>
<class name="IsoDep"
extends="android.nfc.tech.BasicTagTechnology"
@@ -119478,7 +119459,7 @@
deprecated="not deprecated"
visibility="public"
>
-<method name="canMakeReadonly"
+<method name="canMakeReadOnly"
return="boolean"
abstract="false"
native="false"
@@ -119540,7 +119521,7 @@
</exception>
</method>
<method name="getType"
- return="int"
+ return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
@@ -119561,7 +119542,7 @@
visibility="public"
>
</method>
-<method name="makeReadonly"
+<method name="makeReadOnly"
return="boolean"
abstract="false"
native="false"
@@ -119592,10 +119573,10 @@
</exception>
</method>
<field name="MIFARE_CLASSIC"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="101"
+ value=""com.nxp.ndef.mifareclassic""
static="true"
final="true"
deprecated="not deprecated"
@@ -119603,10 +119584,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_1"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="1"
+ value=""org.nfcforum.ndef.type1""
static="true"
final="true"
deprecated="not deprecated"
@@ -119614,10 +119595,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_2"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="2"
+ value=""org.nfcforum.ndef.type2""
static="true"
final="true"
deprecated="not deprecated"
@@ -119625,10 +119606,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_3"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="3"
+ value=""org.nfcforum.ndef.type3""
static="true"
final="true"
deprecated="not deprecated"
@@ -119636,21 +119617,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_4"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="OTHER"
- type="int"
- transient="false"
- volatile="false"
- value="-1"
+ value=""org.nfcforum.ndef.type4""
static="true"
final="true"
deprecated="not deprecated"
@@ -119683,6 +119653,23 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
+<method name="formatReadOnly"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="firstMessage" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
<method name="get"
return="android.nfc.tech.NdefFormatable"
abstract="false"
@@ -119979,8 +119966,8 @@
visibility="public"
>
</method>
-<method name="reconnect"
- return="void"
+<method name="isConnected"
+ return="boolean"
abstract="true"
native="false"
synchronized="false"
@@ -119989,8 +119976,6 @@
deprecated="not deprecated"
visibility="public"
>
-<exception name="IOException" type="java.io.IOException">
-</exception>
</method>
</interface>
</package>
diff --git a/api/current.xml b/api/current.xml
index 16984b5..291d8dbd 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -29418,6 +29418,17 @@
<parameter name="uri" type="android.net.Uri">
</parameter>
</method>
+<method name="setDownloadToBeOtaUpdate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="setMimeType"
return="android.app.DownloadManager.Request"
abstract="false"
@@ -118639,7 +118650,7 @@
visibility="public"
>
</field>
-<field name="ACTION_TECHNOLOGY_DISCOVERED"
+<field name="ACTION_TECH_DISCOVERED"
type="java.lang.String"
transient="false"
volatile="false"
@@ -118708,29 +118719,12 @@
extends="java.lang.Object"
abstract="false"
static="false"
- final="false"
+ final="true"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.os.Parcelable">
</implements>
-<method name="createMockTag"
- return="android.nfc.Tag"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="byte[]">
-</parameter>
-<parameter name="techList" type="int[]">
-</parameter>
-<parameter name="techListExtras" type="android.os.Bundle[]">
-</parameter>
-</method>
<method name="describeContents"
return="int"
abstract="false"
@@ -118878,19 +118872,6 @@
visibility="public"
>
</method>
-<method name="reconnect"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
</class>
<class name="IsoDep"
extends="android.nfc.tech.BasicTagTechnology"
@@ -119478,7 +119459,7 @@
deprecated="not deprecated"
visibility="public"
>
-<method name="canMakeReadonly"
+<method name="canMakeReadOnly"
return="boolean"
abstract="false"
native="false"
@@ -119540,7 +119521,7 @@
</exception>
</method>
<method name="getType"
- return="int"
+ return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
@@ -119561,7 +119542,7 @@
visibility="public"
>
</method>
-<method name="makeReadonly"
+<method name="makeReadOnly"
return="boolean"
abstract="false"
native="false"
@@ -119592,10 +119573,10 @@
</exception>
</method>
<field name="MIFARE_CLASSIC"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="101"
+ value=""com.nxp.ndef.mifareclassic""
static="true"
final="true"
deprecated="not deprecated"
@@ -119603,10 +119584,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_1"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="1"
+ value=""org.nfcforum.ndef.type1""
static="true"
final="true"
deprecated="not deprecated"
@@ -119614,10 +119595,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_2"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="2"
+ value=""org.nfcforum.ndef.type2""
static="true"
final="true"
deprecated="not deprecated"
@@ -119625,10 +119606,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_3"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="3"
+ value=""org.nfcforum.ndef.type3""
static="true"
final="true"
deprecated="not deprecated"
@@ -119636,21 +119617,10 @@
>
</field>
<field name="NFC_FORUM_TYPE_4"
- type="int"
+ type="java.lang.String"
transient="false"
volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="OTHER"
- type="int"
- transient="false"
- volatile="false"
- value="-1"
+ value=""org.nfcforum.ndef.type4""
static="true"
final="true"
deprecated="not deprecated"
@@ -119683,6 +119653,23 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
+<method name="formatReadOnly"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="firstMessage" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
<method name="get"
return="android.nfc.tech.NdefFormatable"
abstract="false"
@@ -119979,8 +119966,8 @@
visibility="public"
>
</method>
-<method name="reconnect"
- return="void"
+<method name="isConnected"
+ return="boolean"
abstract="true"
native="false"
synchronized="false"
@@ -119989,8 +119976,6 @@
deprecated="not deprecated"
visibility="public"
>
-<exception name="IOException" type="java.io.IOException">
-</exception>
</method>
</interface>
</package>
diff --git a/build/phone-hdpi-512-dalvik-heap.mk b/build/phone-hdpi-512-dalvik-heap.mk
index 630cf03..788b686 100644
--- a/build/phone-hdpi-512-dalvik-heap.mk
+++ b/build/phone-hdpi-512-dalvik-heap.mk
@@ -19,5 +19,5 @@
PRODUCT_PROPERTY_OVERRIDES += \
dalvik.vm.heapstartsize=5m \
- dalvik.vm.growthlimit=32m \
+ dalvik.vm.heapgrowthlimit=32m \
dalvik.vm.heapsize=128m
diff --git a/build/tablet-dalvik-heap.mk b/build/tablet-dalvik-heap.mk
index 37c3ec5..826a380 100644
--- a/build/tablet-dalvik-heap.mk
+++ b/build/tablet-dalvik-heap.mk
@@ -18,5 +18,5 @@
PRODUCT_PROPERTY_OVERRIDES += \
dalvik.vm.heapstartsize=5m \
- dalvik.vm.growthlimit=48m \
+ dalvik.vm.heapgrowthlimit=48m \
dalvik.vm.heapsize=256m
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index fb16609..2e70a56 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1781,7 +1781,7 @@
// will return a different value, but we *don't* erase the
// passwords. We only erase them if it has a different
// subscriber ID once it's provisioned.
- if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+ if (telephonyManager.getCurrentPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
IBinder service = ServiceManager.checkService(Context.TELEPHONY_SERVICE);
if (service == null) {
Log.w(TAG, "call to checkService(TELEPHONY_SERVICE) failed");
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 297d246..d37983f 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -339,6 +339,7 @@
private boolean mIsVisibleInDownloadsUi = true;
private boolean mScannable = false;
private boolean mUseSystemCache = false;
+ private boolean mOtaUpdate = false;
/** if a file is designated as a MediaScanner scannable file, the following value is
* stored in the database column {@link Downloads.Impl#COLUMN_MEDIA_SCANNED}.
*/
@@ -605,6 +606,13 @@
}
/**
+ * Set whether the download request is OTA Update. By default, it is set to false.
+ */
+ public void setDownloadToBeOtaUpdate() {
+ mOtaUpdate = true;
+ }
+
+ /**
* Set whether this download should be displayed in the system's Downloads UI. True by
* default.
* @param isVisible whether to display this download in the Downloads UI
@@ -650,6 +658,7 @@
values.put(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, mAllowedNetworkTypes);
values.put(Downloads.Impl.COLUMN_ALLOW_ROAMING, mRoamingAllowed);
values.put(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI, mIsVisibleInDownloadsUi);
+ values.put(Downloads.Impl.COLUMN_IGNORE_SIZE_LIMITS, mOtaUpdate);
return values;
}
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index f9920c7..a990ee9 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -107,9 +107,9 @@
mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
// initialize state
+ mTimePicker.setIs24HourView(mIs24HourView);
mTimePicker.setCurrentHour(mInitialHourOfDay);
mTimePicker.setCurrentMinute(mInitialMinute);
- mTimePicker.setIs24HourView(mIs24HourView);
mTimePicker.setOnTimeChangedListener(this);
}
@@ -144,8 +144,8 @@
super.onRestoreInstanceState(savedInstanceState);
int hour = savedInstanceState.getInt(HOUR);
int minute = savedInstanceState.getInt(MINUTE);
+ mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR));
mTimePicker.setCurrentHour(hour);
mTimePicker.setCurrentMinute(minute);
- mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR));
}
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index fb3744d..4656e15 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -296,12 +296,12 @@
* can use this intent.
*
* <p>This intent will have 3 extras:
- * {@link #EXTRA_STATE} - The current state.
- * {@link #EXTRA_PREVIOUS_STATE}- The previous.
+ * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
+ * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
* {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
*
- * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
+ * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
* {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 4808032..d30a0c6 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -44,10 +44,10 @@
/**
* Intent to start an activity when a tag with NDEF payload is discovered.
* If the tag has and NDEF payload this intent is started before
- * {@link #ACTION_TECHNOLOGY_DISCOVERED}.
+ * {@link #ACTION_TECH_DISCOVERED}.
*
* If any activities respond to this intent neither
- * {@link #ACTION_TECHNOLOGY_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started.
+ * {@link #ACTION_TECH_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
@@ -63,7 +63,7 @@
* If any activities respond to this intent {@link #ACTION_TAG_DISCOVERED} will not be started.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_TECHNOLOGY_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
+ public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
/**
* Intent to start an activity when a tag is discovered.
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index aae75c9..45a3447 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -55,7 +55,7 @@
* not cause any further RF activity or block. Note however that arrays passed to and
* returned by this class are *not* cloned, so be careful not to modify them.
*/
-public class Tag implements Parcelable {
+public final class Tag implements Parcelable {
/*package*/ final byte[] mId;
/*package*/ final int[] mTechList;
/*package*/ final String[] mTechStringList;
@@ -93,6 +93,7 @@
* @param id The tag identifier, can be null
* @param techList must not be null
* @return freshly constructed tag
+ * @hide
*/
public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) {
// set serviceHandle to 0 to indicate mock tag
diff --git a/core/java/android/nfc/tech/BasicTagTechnology.java b/core/java/android/nfc/tech/BasicTagTechnology.java
index 32a850d..7ec807a 100644
--- a/core/java/android/nfc/tech/BasicTagTechnology.java
+++ b/core/java/android/nfc/tech/BasicTagTechnology.java
@@ -53,15 +53,7 @@
}
}
- /**
- * Helper to indicate if {@link #connect} has succeeded.
- * <p>
- * Does not cause RF activity, and does not block.
- * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed
- * to be within range. Applications must still handle {@link java.io.IOException}
- * while using methods that require a connection in case the connection is lost after this
- * method returns.
- */
+ @Override
public boolean isConnected() {
if (!mIsConnected) {
return false;
@@ -94,6 +86,7 @@
}
}
+ /** @hide */
@Override
public void reconnect() throws IOException {
if (!mIsConnected) {
diff --git a/core/java/android/nfc/tech/Ndef.java b/core/java/android/nfc/tech/Ndef.java
index c6804f9..39ff282 100644
--- a/core/java/android/nfc/tech/Ndef.java
+++ b/core/java/android/nfc/tech/Ndef.java
@@ -61,12 +61,31 @@
/** @hide */
public static final String EXTRA_NDEF_TYPE = "ndeftype";
- public static final int OTHER = -1;
- public static final int NFC_FORUM_TYPE_1 = 1;
- public static final int NFC_FORUM_TYPE_2 = 2;
- public static final int NFC_FORUM_TYPE_3 = 3;
- public static final int NFC_FORUM_TYPE_4 = 4;
- public static final int MIFARE_CLASSIC = 101;
+ /** @hide */
+ public static final int TYPE_OTHER = -1;
+ /** @hide */
+ public static final int TYPE_1 = 1;
+ /** @hide */
+ public static final int TYPE_2 = 2;
+ /** @hide */
+ public static final int TYPE_3 = 3;
+ /** @hide */
+ public static final int TYPE_4 = 4;
+ /** @hide */
+ public static final int TYPE_MIFARE_CLASSIC = 101;
+
+ /** @hide */
+ public static final String UNKNOWN = "android.ndef.unknown";
+
+ public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1";
+
+ public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2";
+
+ public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3";
+
+ public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4";
+
+ public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic";
private final int mMaxNdefSize;
private final int mCardState;
@@ -118,18 +137,27 @@
* Get NDEF tag type.
* <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2},
* {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4},
- * {@link #MIFARE_CLASSIC} or {@link #OTHER}.
- * <p>Platforms of this API revision will always return one of the above
- * values. Platforms at future API revisions may return other values, which
- * can be treated as {@link #OTHER} by applications targeting this API.
+ * {@link #MIFARE_CLASSIC} or another NDEF tag type that is not yet in the
+ * Android API.
* <p>Android devices with NFC support must always correctly enumerate
* NFC Forum tag types, and may optionally enumerate
* {@link #MIFARE_CLASSIC} since it requires proprietary technology.
- * Devices that cannot enumerate {@link #MIFARE_CLASSIC} will use
- * {@link #OTHER} instead.
*/
- public int getType() {
- return mNdefType;
+ public String getType() {
+ switch (mNdefType) {
+ case TYPE_1:
+ return NFC_FORUM_TYPE_1;
+ case TYPE_2:
+ return NFC_FORUM_TYPE_2;
+ case TYPE_3:
+ return NFC_FORUM_TYPE_3;
+ case TYPE_4:
+ return NFC_FORUM_TYPE_4;
+ case TYPE_MIFARE_CLASSIC:
+ return MIFARE_CLASSIC;
+ default:
+ return UNKNOWN;
+ }
}
/**
@@ -217,10 +245,10 @@
/**
* Indicates whether a tag can be made read-only with
- * {@link #makeReadonly()}
+ * {@link #makeReadOnly()}
*/
- public boolean canMakeReadonly() {
- if (mNdefType == NFC_FORUM_TYPE_1 || mNdefType == NFC_FORUM_TYPE_2) {
+ public boolean canMakeReadOnly() {
+ if (mNdefType == TYPE_1 || mNdefType == TYPE_2) {
return true;
} else {
return false;
@@ -234,7 +262,7 @@
* This is a one-way process and can not be reverted!
* @throws IOException
*/
- public boolean makeReadonly() throws IOException {
+ public boolean makeReadOnly() throws IOException {
checkConnected();
try {
diff --git a/core/java/android/nfc/tech/NdefFormatable.java b/core/java/android/nfc/tech/NdefFormatable.java
index 2919c43..e2828b5 100644
--- a/core/java/android/nfc/tech/NdefFormatable.java
+++ b/core/java/android/nfc/tech/NdefFormatable.java
@@ -65,8 +65,25 @@
/**
* Formats a tag as NDEF, if possible. You may supply a first
* NdefMessage to be written on the tag.
+ * <p>Either all steps succeed, or an IOException is thrown if any one step
+ * fails.
*/
public void format(NdefMessage firstMessage) throws IOException, FormatException {
+ format(firstMessage, false);
+ }
+
+ /**
+ * Formats a tag as NDEF, if possible. You may supply a first
+ * NdefMessage to be written on the tag.
+ * <p>Either all steps succeed, or an IOException is thrown if any one step
+ * fails.
+ */
+ public void formatReadOnly(NdefMessage firstMessage) throws IOException, FormatException {
+ format(firstMessage, true);
+ }
+
+ /*package*/ void format(NdefMessage firstMessage, boolean makeReadOnly) throws IOException,
+ FormatException {
checkConnected();
try {
@@ -101,6 +118,21 @@
} else {
throw new IOException();
}
+ // optionally make read-only
+ if (makeReadOnly) {
+ errorCode = tagService.ndefMakeReadOnly(serviceHandle);
+ switch (errorCode) {
+ case ErrorCodes.SUCCESS:
+ break;
+ case ErrorCodes.ERROR_IO:
+ throw new IOException();
+ case ErrorCodes.ERROR_INVALID_PARAM:
+ throw new IOException();
+ default:
+ // Should not happen
+ throw new IOException();
+ }
+ }
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
}
diff --git a/core/java/android/nfc/tech/TagTechnology.java b/core/java/android/nfc/tech/TagTechnology.java
index c8ccdcf..50df865 100644
--- a/core/java/android/nfc/tech/TagTechnology.java
+++ b/core/java/android/nfc/tech/TagTechnology.java
@@ -121,6 +121,7 @@
* @see #connect()
* @see #close()
* @throws IOException
+ * @hide
*/
public void reconnect() throws IOException;
@@ -137,4 +138,15 @@
* @see #reconnect()
*/
public void close() throws IOException;
+
+ /**
+ * Helper to indicate if {@link #connect} has succeeded.
+ * <p>
+ * Does not cause RF activity, and does not block.
+ * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed
+ * to be within range. Applications must still handle {@link java.io.IOException}
+ * while using methods that require a connection in case the connection is lost after this
+ * method returns.
+ */
+ public boolean isConnected();
}
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 013edd3..ad0140b 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -397,6 +397,12 @@
*/
public static final String COLUMN_LAST_UPDATESRC = "lastUpdateSrc";
+ /** Set this column to true if the given download should ignore the mobile network
+ * download limits.
+ * <P>Type: Boolean</P>
+ */
+ public static final String COLUMN_IGNORE_SIZE_LIMITS = "otaupdate";
+
/**
* default value for {@link #COLUMN_LAST_UPDATESRC}.
* This value is used when this column's value is not relevant.
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 44887ed..912a88d 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -36,6 +36,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.LogPrinter;
@@ -206,8 +207,14 @@
@Override
public void setFixedSize(int width, int height) {
- throw new UnsupportedOperationException(
- "Wallpapers currently only support sizing from layout");
+ if (Process.myUid() != Process.SYSTEM_UID) {
+ // Regular apps can't do this. It can only work for
+ // certain designs of window animations, so you can't
+ // rely on it.
+ throw new UnsupportedOperationException(
+ "Wallpapers currently only support sizing from layout");
+ }
+ super.setFixedSize(width, height);
}
public void setKeepScreenOn(boolean screenOn) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 48f40c3..71d55f7 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -547,7 +547,7 @@
}
onPreDraw(dirty);
-
+
HardwareCanvas canvas = mCanvas;
attachInfo.mHardwareCanvas = canvas;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6c5bdb6..9db43a1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -73,7 +73,6 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
import java.util.WeakHashMap;
/**
@@ -2375,6 +2374,7 @@
})
int mLayerType = LAYER_TYPE_NONE;
Paint mLayerPaint;
+ Rect mLocalDirtyRect;
/**
* Simple constructor to use when creating a view from code.
@@ -6910,7 +6910,7 @@
* well. This is usually true for a full invalidate, but may be set to false if the
* View's contents or dimensions have not changed.
*/
- private void invalidate(boolean invalidateCache) {
+ void invalidate(boolean invalidateCache) {
if (ViewDebug.TRACE_HIERARCHY) {
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
}
@@ -8173,7 +8173,9 @@
}
mLayerType = layerType;
- mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : (paint == null ? new Paint() : paint);
+ final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
+ mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
+ mLocalDirtyRect = layerDisabled ? null : new Rect();
invalidateParentCaches();
invalidate(true);
@@ -8219,8 +8221,10 @@
if (mHardwareLayer == null) {
mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
width, height, isOpaque());
+ mLocalDirtyRect.setEmpty();
} else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
mHardwareLayer.resize(width, height);
+ mLocalDirtyRect.setEmpty();
}
Canvas currentCanvas = mAttachInfo.mHardwareCanvas;
@@ -8228,8 +8232,8 @@
mAttachInfo.mHardwareCanvas = canvas;
try {
canvas.setViewport(width, height);
- // TODO: We should pass the dirty rect
- canvas.onPreDraw(null);
+ canvas.onPreDraw(mLocalDirtyRect);
+ mLocalDirtyRect.setEmpty();
final int restoreCount = canvas.save();
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d0509b2..09e1d89 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -347,6 +347,10 @@
// views during a transition when they otherwise would have become gone/invisible
private ArrayList<View> mVisibilityChangingChildren;
+ // Indicates whether this container will use its children layers to draw
+ @ViewDebug.ExportedProperty(category = "drawing")
+ private boolean mDrawLayers = true;
+
public ViewGroup(Context context) {
super(context);
initViewGroup();
@@ -2147,7 +2151,7 @@
flags = mGroupFlags;
if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) {
- invalidate();
+ invalidate(true);
}
if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 &&
@@ -2203,7 +2207,7 @@
}
}
- invalidate();
+ invalidate(true);
}
/**
@@ -2262,7 +2266,7 @@
boolean scalingRequired = false;
boolean caching;
- int layerType = child.getLayerType();
+ int layerType = mDrawLayers ? child.getLayerType() : LAYER_TYPE_NONE;
final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
@@ -2444,17 +2448,12 @@
layerType != LAYER_TYPE_NONE) {
layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
}
- if (layerType != LAYER_TYPE_NONE) {
- child.mLayerPaint.setAlpha(multipliedAlpha);
- } else {
+ if (layerType == LAYER_TYPE_NONE) {
canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct,
multipliedAlpha, layerFlags);
}
} else {
// Alpha is handled by the child directly, clobber the layer's alpha
- if (layerType != LAYER_TYPE_NONE) {
- child.mLayerPaint.setAlpha(255);
- }
child.mPrivateFlags |= ALPHA_SET;
}
}
@@ -2485,6 +2484,7 @@
if (layerType == LAYER_TYPE_HARDWARE) {
final HardwareLayer layer = child.getHardwareLayer();
if (layer != null && layer.isValid()) {
+ child.mLayerPaint.setAlpha((int) (alpha * 255));
((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, child.mLayerPaint);
layerRendered = true;
} else {
@@ -2543,10 +2543,10 @@
// invalidation is the trigger to recreate display lists, so if we're using
// display lists to render, force an invalidate to allow the animation to
// continue drawing another frame
- invalidate();
+ invalidate(true);
if (a instanceof AlphaAnimation) {
// alpha animations should cause the child to recreate its display list
- child.invalidate();
+ child.invalidate(true);
}
}
@@ -2556,6 +2556,17 @@
}
/**
+ *
+ * @param enabled True if children should be drawn with layers, false otherwise.
+ *
+ * @hide
+ */
+ public void setChildrenLayersEnabled(boolean enabled) {
+ mDrawLayers = enabled;
+ invalidate(true);
+ }
+
+ /**
* By default, children are clipped to their bounds before drawing. This
* allows view groups to override this behavior for animations, etc.
*
@@ -2587,7 +2598,6 @@
final View[] children = mChildren;
final int count = mChildrenCount;
for (int i = 0; i < count; i++) {
-
children[i].setSelected(selected);
}
}
@@ -2600,7 +2610,6 @@
final View[] children = mChildren;
final int count = mChildrenCount;
for (int i = 0; i < count; i++) {
-
children[i].setActivated(activated);
}
}
@@ -2793,7 +2802,7 @@
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
requestLayout();
- invalidate();
+ invalidate(true);
addViewInner(child, index, params, false);
}
@@ -3075,7 +3084,7 @@
public void removeView(View view) {
removeViewInternal(view);
requestLayout();
- invalidate();
+ invalidate(true);
}
/**
@@ -3107,7 +3116,7 @@
public void removeViewAt(int index) {
removeViewInternal(index, getChildAt(index));
requestLayout();
- invalidate();
+ invalidate(true);
}
/**
@@ -3119,7 +3128,7 @@
public void removeViews(int start, int count) {
removeViewsInternal(start, count);
requestLayout();
- invalidate();
+ invalidate(true);
}
private void removeViewInternal(View view) {
@@ -3244,7 +3253,7 @@
public void removeAllViews() {
removeAllViewsInLayout();
requestLayout();
- invalidate();
+ invalidate(true);
}
/**
@@ -3478,16 +3487,19 @@
if (child.mLayerType != LAYER_TYPE_NONE) {
mPrivateFlags |= INVALIDATED;
mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ child.mLocalDirtyRect.setEmpty();
}
do {
View view = null;
if (parent instanceof View) {
view = (View) parent;
- if (view.mLayerType != LAYER_TYPE_NONE &&
- view.getParent() instanceof View) {
- final View grandParent = (View) view.getParent();
- grandParent.mPrivateFlags |= INVALIDATED;
- grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ if (view.mLayerType != LAYER_TYPE_NONE) {
+ view.mLocalDirtyRect.setEmpty();
+ if (view.getParent() instanceof View) {
+ final View grandParent = (View) view.getParent();
+ grandParent.mPrivateFlags |= INVALIDATED;
+ grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ }
}
if ((view.mPrivateFlags & DIRTY_MASK) != 0) {
// already marked dirty - we're done
@@ -3525,6 +3537,12 @@
// Make sure we do not set both flags at the same time
int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
+ if (child.mLayerType != LAYER_TYPE_NONE) {
+ mPrivateFlags |= INVALIDATED;
+ mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ child.mLocalDirtyRect.union(dirty);
+ }
+
final int[] location = attachInfo.mInvalidateChildLocation;
location[CHILD_LEFT_INDEX] = child.mLeft;
location[CHILD_TOP_INDEX] = child.mTop;
@@ -3538,10 +3556,6 @@
(int) (boundingRect.bottom + 0.5f));
}
- if (child.mLayerType != LAYER_TYPE_NONE) {
- mPrivateFlags |= INVALIDATED;
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
- }
do {
View view = null;
if (parent instanceof View) {
@@ -3622,6 +3636,10 @@
location[CHILD_LEFT_INDEX] = left;
location[CHILD_TOP_INDEX] = top;
+ if (mLayerType != LAYER_TYPE_NONE) {
+ mLocalDirtyRect.union(dirty);
+ }
+
return mParent;
}
} else {
@@ -3630,8 +3648,11 @@
location[CHILD_LEFT_INDEX] = mLeft;
location[CHILD_TOP_INDEX] = mTop;
- dirty.set(0, 0, mRight - location[CHILD_LEFT_INDEX],
- mBottom - location[CHILD_TOP_INDEX]);
+ dirty.set(0, 0, mRight - mLeft, mBottom - mTop);
+
+ if (mLayerType != LAYER_TYPE_NONE) {
+ mLocalDirtyRect.union(dirty);
+ }
return mParent;
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c84e314..fa99eae 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -7144,6 +7144,16 @@
setContentScrollTo(msg.arg1, msg.arg2);
break;
case SCROLL_TO_MSG_ID:
+ if (((Boolean) msg.obj).booleanValue()) {
+ // This scroll is intended to bring the textfield into
+ // view, but is only necessary if the IME is showing
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm == null || !imm.isAcceptingText()
+ || (!imm.isActive(WebView.this) && (!inEditingMode()
+ || !imm.isActive(mWebTextView)))) {
+ break;
+ }
+ }
if (setContentScrollTo(msg.arg1, msg.arg2)) {
// if we can't scroll to the exact position due to pin,
// send a message to WebCore to re-scroll when we get a
@@ -8151,7 +8161,7 @@
* @hide only used by the Browser
*/
public void setExpandedTileBounds(boolean enabled) {
- mWebViewCore.sendMessage(EventHub.SET_EXPANDED_TILE_BOUNDS, enabled ? 1 : 0, 0);
+ nativeSetExpandedTileBounds(enabled);
}
/**
@@ -8310,6 +8320,8 @@
static final int NO_LEFTEDGE = -1;
native int nativeGetBlockLeftEdge(int x, int y, float scale);
+ private native void nativeSetExpandedTileBounds(boolean enabled);
+
// Returns a pointer to the scrollable LayerAndroid at the given point.
private native int nativeScrollableLayer(int x, int y, Rect scrollRect,
Rect scrollBounds);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 6536e45..5bdf408 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -578,8 +578,6 @@
private native void nativeSetJsFlags(String flags);
- private native void nativeSetExpandedTileBounds(boolean enabled);
-
/**
* Delete text from start to end in the focused textfield. If there is no
* focus, or if start == end, silently fail. If start and end are out of
@@ -1001,8 +999,6 @@
static final int PROXY_CHANGED = 193;
- static final int SET_EXPANDED_TILE_BOUNDS = 194;
-
// private message ids
private static final int DESTROY = 200;
@@ -1562,10 +1558,6 @@
mWebView.mPrivateHandler.obtainMessage(WebView.AUTOFILL_COMPLETE, null)
.sendToTarget();
break;
-
- case EventHub.SET_EXPANDED_TILE_BOUNDS:
- nativeSetExpandedTileBounds(msg.arg1 == 1);
- break;
}
}
};
@@ -2128,7 +2120,7 @@
}
// called by JNI
- private void contentScrollTo(int x, int y) {
+ private void contentScrollTo(int x, int y, boolean onlyIfImeIsShowing) {
if (!mBrowserFrame.firstLayoutDone()) {
/*
* WebKit restore state will be called before didFirstLayout(),
@@ -2141,7 +2133,8 @@
}
if (mWebView != null) {
Message msg = Message.obtain(mWebView.mPrivateHandler,
- WebView.SCROLL_TO_MSG_ID, x, y);
+ WebView.SCROLL_TO_MSG_ID, x, y,
+ Boolean.valueOf(onlyIfImeIsShowing));
if (mDrawIsScheduled) {
mEventHub.sendMessage(Message.obtain(null,
EventHub.MESSAGE_RELAY, msg));
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 595c634..8fde247 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -117,7 +117,11 @@
synchronized (mLock) {
updateWallpaperLocked();
}
- surfaceHolder.setSizeFromLayout();
+ surfaceHolder.setFixedSize(getDesiredMinimumWidth(), getDesiredMinimumHeight());
+ // Used a fixed size surface, because we are special. We can do
+ // this because we know the current design of window animations doesn't
+ // cause this to break.
+ //surfaceHolder.setSizeFromLayout();
}
@Override
diff --git a/core/res/res/drawable-hdpi/ic_audio_alarm.png b/core/res/res/drawable-hdpi/ic_audio_alarm.png
new file mode 100644
index 0000000..1b41de4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_audio_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-hdpi/ic_audio_alarm_mute.png
new file mode 100644
index 0000000..e31fdb8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_audio_alarm_mute.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_notification.png b/core/res/res/drawable-hdpi/ic_audio_notification.png
new file mode 100644
index 0000000..00e8f8a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_audio_notification.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_notification_mute.png b/core/res/res/drawable-hdpi/ic_audio_notification_mute.png
new file mode 100644
index 0000000..a350e16
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_audio_notification_mute.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_vol.png b/core/res/res/drawable-hdpi/ic_audio_vol.png
new file mode 100644
index 0000000..cf3f3f5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_audio_vol.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_vol_mute.png b/core/res/res/drawable-hdpi/ic_audio_vol_mute.png
new file mode 100644
index 0000000..c4ac4ef
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_audio_vol_mute.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_emergency.png b/core/res/res/drawable-hdpi/ic_emergency.png
index b4465ff..89c05e3 100644
--- a/core/res/res/drawable-hdpi/ic_emergency.png
+++ b/core/res/res/drawable-hdpi/ic_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_alarm.png b/core/res/res/drawable-mdpi/ic_audio_alarm.png
new file mode 100644
index 0000000..fab95aa
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_audio_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-mdpi/ic_audio_alarm_mute.png
new file mode 100644
index 0000000..ca3ed93
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_audio_alarm_mute.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_notification.png b/core/res/res/drawable-mdpi/ic_audio_notification.png
new file mode 100644
index 0000000..b41ccd0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_audio_notification.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_notification_mute.png b/core/res/res/drawable-mdpi/ic_audio_notification_mute.png
new file mode 100644
index 0000000..f0b6d8a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_audio_notification_mute.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_vol.png b/core/res/res/drawable-mdpi/ic_audio_vol.png
new file mode 100644
index 0000000..049e92a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_audio_vol.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_vol_mute.png b/core/res/res/drawable-mdpi/ic_audio_vol_mute.png
new file mode 100644
index 0000000..be71492
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_audio_vol_mute.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim0.png b/core/res/res/drawable-mdpi/stat_sys_download_anim0.png
index 39e4ccb..c6f2f4e 100644
--- a/core/res/res/drawable-mdpi/stat_sys_download_anim0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_download_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png
index 5620cc8..f804e5e 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png
Binary files differ
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml b/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
index 16bfc31..1783088 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
@@ -61,7 +61,6 @@
android:textSize="24sp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:background="@drawable/lockscreen_password_field_dark"
- android:hint="@string/keyguard_password_entry_touch_hint"
android:textColor="#ffffffff"
/>
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
index b87b51f..63241dd 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
@@ -57,7 +57,6 @@
android:layout_marginBottom="5dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:background="@drawable/lockscreen_password_field_dark"
- android:hint="@string/keyguard_password_entry_touch_hint"
android:textColor="#ffffffff"
/>
diff --git a/data/sounds/alarms/ogg/Cesium.ogg b/data/sounds/alarms/ogg/Cesium.ogg
index 76eca08..a8c379a 100644
--- a/data/sounds/alarms/ogg/Cesium.ogg
+++ b/data/sounds/alarms/ogg/Cesium.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Effect_Tick.ogg b/data/sounds/effects/ogg/Effect_Tick.ogg
index b379019..a997fe1 100644
--- a/data/sounds/effects/ogg/Effect_Tick.ogg
+++ b/data/sounds/effects/ogg/Effect_Tick.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/LowBattery.ogg b/data/sounds/effects/ogg/LowBattery.ogg
index c21218c..dfb5d88 100644
--- a/data/sounds/effects/ogg/LowBattery.ogg
+++ b/data/sounds/effects/ogg/LowBattery.ogg
Binary files differ
diff --git a/docs/html/guide/developing/building/index.jd b/docs/html/guide/developing/building/index.jd
index b001ebc..25a6e23 100644
--- a/docs/html/guide/developing/building/index.jd
+++ b/docs/html/guide/developing/building/index.jd
@@ -37,7 +37,7 @@
<p>The following diagram depicts the components involved in building and running an application:</p>
- <img src="/images/build-simplified.png" />
+ <img src="{@docRoot}images/build-simplified.png" />
<h2 id="detailed-build">A Detailed Look at the Build Process</h2>
@@ -49,7 +49,7 @@
tools and processes are masked from you. The following diagram depicts the different tools and
processes that are involved in a build:</p>
- <p><img src="/images/build.png" /></p>
+ <p><img src="{@docRoot}images/build.png" /></p>
<p>The general process for a typical build is outlined below:</p>
diff --git a/docs/html/guide/developing/debugging/debugging-tracing.jd b/docs/html/guide/developing/debugging/debugging-tracing.jd
index dcc889d..0401966 100644
--- a/docs/html/guide/developing/debugging/debugging-tracing.jd
+++ b/docs/html/guide/developing/debugging/debugging-tracing.jd
@@ -67,7 +67,7 @@
selected method. The method in this case is <code>LoadListener.nativeFinished()</code> and it was selected in
the profile view.</p>
- <img src="/images/traceview_timeline.png"
+ <img src="{@docRoot}images/traceview_timeline.png"
alt="Traceview timeline panel"
width="893"
height="284" />
@@ -87,7 +87,7 @@
<code>LoadListener.nativeFinished();</code> looking at the timeline panel shows that one of those calls took
an unusually long time.</p>
- <img src="/images/traceview_profile.png"
+ <img src="{@docRoot}images/traceview_profile.png"
alt="Traceview profile panel."
width="892"
height="630" />
diff --git a/docs/html/guide/developing/debugging/index.jd b/docs/html/guide/developing/debugging/index.jd
index f9202ce..1f1a4ca 100644
--- a/docs/html/guide/developing/debugging/index.jd
+++ b/docs/html/guide/developing/debugging/index.jd
@@ -62,7 +62,7 @@
<p>Figure 1 shows how the various debugging tools work together in a typical
debugging environment.</p>
- <img src="/images/debugging.png"
+ <img src="{@docRoot}images/debugging.png"
alt="Debugging workflow" />
<p class="img-caption><strong>Figure 1. </strong> Debugging Workflow</p>
diff --git a/docs/html/guide/developing/devices/emulator.jd b/docs/html/guide/developing/devices/emulator.jd
index a3cd5c5..53c1407 100644
--- a/docs/html/guide/developing/devices/emulator.jd
+++ b/docs/html/guide/developing/devices/emulator.jd
@@ -33,7 +33,7 @@
</div>
</div>
-<img src="/images/emulator-wvga800l.png" alt="Image of the Android Emulator"
+<img src="{@docRoot}images/emulator-wvga800l.png" alt="Image of the Android Emulator"
width="367" height="349" style="margin-left:2em;float:right;"/>
<p>The Android SDK includes a virtual mobile device emulator
that runs on your computer. The emulator lets you prototype, develop, and test
diff --git a/docs/html/guide/developing/projects/index.jd b/docs/html/guide/developing/projects/index.jd
index 45fd5a1..609a71a 100644
--- a/docs/html/guide/developing/projects/index.jd
+++ b/docs/html/guide/developing/projects/index.jd
@@ -471,7 +471,7 @@
<code>MyLibrary/src</code>. Eclipse shows an error on one of them because they
are duplicate links to a single class.</p>
-<img src="/images/developing/lib-migration-0.png" alt="">
+<img src="{@docRoot}images/developing/lib-migration-0.png" alt="">
<p class="img-caption"><strong>Figure 1.</strong> Library project migration error</p>
<p>To fix the error, remove the linked folder that <em>does not</em> contain the
<code>_src</code> suffix. </p>
@@ -481,14 +481,14 @@
<code>MyLibrary</code> folder) and choose <strong>Build Path</strong> >
<strong>Remove from Build Path</strong>, as shown in figure 2.</li>
-<img src="/images/developing/lib-migration-1.png" style="height:600px"
+<img src="{@docRoot}images/developing/lib-migration-1.png" style="height:600px"
alt="">
<p class="img-caption"><strong>Figure 2.</strong> Remove from Build Path menu item</p>
<li>Next, when asked about unlinking the folder from the project, select
<strong>Yes</strong>, as shown in figure 3.</li>
-<img src="/images/developing/lib-migration-2.png" alt="">
+<img src="{@docRoot}images/developing/lib-migration-2.png" alt="">
<p class="img-caption"><strong>Figure 3.</strong> Unlink folder confirmation window</p>
</ol>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 270d153..cf0593c 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -466,34 +466,34 @@
<li><a href="<?cs var:toroot ?>guide/developing/tools/logcat.html">logcat</a></li>
<li><a href="<?cs var:toroot ?>guide/developing/tools/mksdcard.html">mksdcard</a></li>
- <li><a href="/guide/developing/tools/monkey.html">Monkey</a></li>
+ <li><a href="<?cs var:toroot ?>guide/developing/tools/monkey.html">Monkey</a></li>
<li class="toggle-list">
<div>
- <a href="/guide/developing/tools/monkeyrunner_concepts.html">
+ <a href="<?cs var:toroot ?>guide/developing/tools/monkeyrunner_concepts.html">
<span class="en">monkeyrunner</span>
</a>
</div>
<ul>
<li>
- <a href="/guide/developing/tools/MonkeyDevice.html">
+ <a href="<?cs var:toroot ?>guide/developing/tools/MonkeyDevice.html">
<span class="en">MonkeyDevice</span>
</a>
</li>
<li>
- <a href="/guide/developing/tools/MonkeyImage.html">
+ <a href="<?cs var:toroot ?>guide/developing/tools/MonkeyImage.html">
<span class="en">MonkeyImage</span>
</a>
</li>
<li>
- <a href="/guide/developing/tools/MonkeyRunner.html">
+ <a href="<?cs var:toroot ?>guide/developing/tools/MonkeyRunner.html">
<span class="en">MonkeyRunner</span>
</a>
</li>
</ul>
</li>
- <li><a href="/guide/developing/tools/proguard.html">ProGuard</a></li>
- <li><a href="/guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
- <li><a href="/guide/developing/tools/traceview.html">Traceview</a></li>
+ <li><a href="<?cs var:toroot ?>guide/developing/tools/proguard.html">ProGuard</a></li>
+ <li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
+ <li><a href="<?cs var:toroot ?>guide/developing/tools/traceview.html">Traceview</a></li>
<li><a href="<?cs var:toroot ?>guide/developing/tools/zipalign.html">zipalign</a></li>
</ul>
</li>
diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd
index 376bf6a..b8d1928 100644
--- a/docs/html/guide/topics/ui/actionbar.jd
+++ b/docs/html/guide/topics/ui/actionbar.jd
@@ -12,20 +12,25 @@
<li>Provides action items from the Options Menu and modes of navigating around the
application</li>
<li>Supports custom views, including an embedded search box</li>
- <li>Requires API Level HONEYCOMB</li>
+ <li>Requires API Level 11</li>
</ul>
<h2>In this document</h2>
<ol>
- <li><a href="#Adding">Adding the Action Bar</a></li>
+ <li><a href="#Adding">Adding the Action Bar</a>
+ <ol>
+ <li><a href="#Removing">Removing the Action Bar</a></li>
+ </ol>
+ </li>
<li><a href="#ActionItems">Adding Action Items</a>
<ol>
- <li><a href="#Home">Using the application icon as an action item</a></li>
+ <li><a href="#Home">Using the app icon as an action item</a></li>
</ol>
</li>
<li><a href="#ActionView">Adding an Action View</a></li>
<li><a href="#Tabs">Adding Tabs</a></li>
<li><a href="#Dropdown">Adding Drop-down Navigation</a></li>
+ <li><a href="#Style">Styling the Action Bar</a></li>
</ol>
<h2>Key classes</h2>
@@ -42,96 +47,129 @@
</div>
<p>The Action Bar is a widget for activities that replaces the traditional title bar at
-the top of an activity. By default, the Action Bar includes the application logo on the left side,
-followed by the activity title. The Action Bar offers several useful features for
-applications—especially those targeted to tablet devices. The Action Bar features include
-the ability to:</p>
+the top of the screen. By default, the Action Bar includes the application logo on the left side,
+followed by the activity title, and any available items from the Options Menu on the right side. The
+Action Bar offers several useful features, including the ability to:</p>
<ul>
<li>Display items from the <a
-href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">Options Menu</a> as "action
-items"—providing instant access to key user actions. (Menu items not appearing as action
-items are placed in the Overflow Menu, revealed by a drop-down in the Action Bar.)</li>
+href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">Options Menu</a> directly in the Action
+Bar, as "action
+items"—providing instant access to key user actions.
+ <p>Menu items that do not appear as action items are placed in the overflow menu, revealed
+by a drop-down list in the Action Bar.</p></li>
<li>Provide tabs for navigating between <a
href="{@docRoot}guide/topics/fundamentals/fragments.html">fragments</a>.</li>
- <li>Provide drop-down navigation items.</li>
- <li>Provide interactive "action views" in place of action items.</li>
- <li>Use the application logo as a "return home" or "up" navigation action.</li>
+ <li>Provide a drop-down list for navigation.</li>
+ <li>Provide interactive "action views" in place of action items (such as a search box).</li>
</ul>
<img src="{@docRoot}images/ui/actionbar.png" height="36" alt="" />
-<p class="img-caption"><strong>Figure 1.</strong> A screenshot of the Action Bar in the NotePad
-sample application, containing action items to save and delete the note.</p>
+
+<p class="img-caption"><strong>Figure 1.</strong> A screenshot of the Action Bar in the Email
+application, containing action items to compose new email and refresh the inbox.</p>
<h2 id="Adding">Adding the Action Bar</h2>
-<p>To add the Action Bar to your activities, simply target your application for HONEYCOMB or later,
-using the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code
-<uses-sdk>}</a> element. That is, by setting either the {@code android:minSdkVersion} or
-{@code android:targetSdkVersion} to HONEYCOMB or later, each activity in your application will
-include the Action Bar when running on devices with HONEYCOMB or later. For example:</p>
+<p>The Action Bar is included by default in all activities that target Android 3.0 or greater. More
+specifically, all activities that use the new "holographic" theme include the Action Bar, and any
+application that targets Android 3.0 automatically receives this theme. An application is considered
+to "target" Android 3.0 when it has set either the {@code android:minSdkVersion} or {@code
+android:targetSdkVersion} attribute in the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a> element to
+{@code "11"} or greater. For example:</p>
<pre>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.helloworld"
android:versionCode="1"
android:versionName="1.0">
- <b><uses-sdk android:minSdkVersion="Froyo" /></b>
+ <uses-sdk android:minSdkVersion="4"
+ <b>android:targetSdkVersion="11"</b> />
<application ... >
...
</application>
</manifest>
</pre>
-<p>This also enables the "Holographic" theme for all your activities, which is the new default
-application theme for HONEYCOMB and later.</p>
+<p>In this example, the application requires a minimum version of API
+Level 4 (Android 1.6), but it also targets API Level 11 (Android 3.0). This way, when
+the application is installed on a device running Android 3.0 or greater, the system applies the
+holographic theme to each activity, and thus, each activity includes the Action Bar.</p>
-<p class="note"><strong>Note:</strong> In order for the Holographic theme to be applied based on
-the target platform version, the <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a>
-element must appear <em>before</em> the <a
-href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
-element.</p>
+<p>However, if you want to use Action Bar APIs, such as to add tabs or modify Action Bar styles,
+you need to set the {@code android:minSdkVersion} to {@code "11"}, so you can access the
+{@link android.app.ActionBar} class.</p>
-<h3>Hide the Action Bar</h3>
-<p>If you want to hide the Action Bar for a particular activity, set the activity theme to
-{@code android:style/Theme.NoTitleBar}. For example:</p>
+<h3 id="Removing">Removing the Action Bar</h3>
+
+<p>If you want to remove the Action Bar for a particular activity, set the activity theme to
+{@link android.R.style#Theme_Holo_NoActionBar Theme.Holo.NoActionBar}. For example:</p>
<pre>
-<activity android:theme="@android:style/Theme.NoTitleBar">
+<activity android:theme="@android:style/Theme.Holo.NoActionBar">
</pre>
+<p class="note"><strong>Tip:</strong> If you have a custom activity theme in which you'd like to
+remove the Action Bar, set the {@link android.R.styleable#Theme_windowActionBar
+android:windowActionBar} style property {@code false}. See <a href="#Style">Styling the Action
+Bar</a> for more about Action Bar styles.</p>
+
+<p>You can also hide the Action Bar at runtime by calling {@link android.app.ActionBar#hide},
+then show it again by calling {@link android.app.ActionBar#show}. For example:</p>
+
+<pre>
+ActionBar actionBar = getActionBar();
+actionBar.hide();
+</pre>
+
+<p>When the Action Bar hides, the system adjusts your activity content to fill all the
+available screen space.</p>
+
+<p class="note"><strong>Note:</strong> If you remove the Action Bar using a theme, then the
+window will not allow the Action Bar at all, so you cannot add it at runtime—calling
+{@link android.app.Activity#getActionBar getActionBar()} will return null.</p>
+
<h2 id="ActionItems">Adding Action Items</h2>
-<p>For each action item you want to add to the Action Bar, you must add a menu item to the
-activity's <a href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">Options Menu</a> and declare
-that the item be shown as an action.</p>
+<p>An action item is simply a menu item from the <a
+href="{@docRoot}guide/topics/ui/menus.html#OptionsMenu">Options Menu</a> which you declare should
+appear directly in the Action Bar. An action item can include an icon and/or text. If a menu
+item does not appear as an action item, then the system places it in the overflow menu, which
+the user can open with the menu icon on the right side of the Action Bar.</p>
<div class="figure" style="width:359px">
<img src="{@docRoot}images/ui/actionbar-item-withtext.png" height="57" alt="" />
<p class="img-caption"><strong>Figure 2.</strong> A screenshot from an Action Bar with two
-action items.</p>
+action items and the overflow menu.</p>
</div>
+<p>When the activity first starts, the system populates the Action Bar and overflow menu by calling
+{@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} for your activity. As
+discussed in the guide to <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>, it's in
+this callback method that you define the Options Menu for the activity.</p>
+
<p>You can specify a menu item to appear as an action item—if there is room
-for it—from the <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu
+for it—from your <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu
resource</a> by declaring {@code
-android:showAsAction="ifRoom"} for the {@code <item>} element. This way, the item will display
-in the Action Bar for quick access only if there is room available for it—if there's not
-enough room, the item is placed the Overflow Menu (revealed by the menu icon on the right side
-of the Action Bar). From your application code, you can specify the item to appear as an action item
-by calling {@link android.view.MenuItem#setShowAsAction setShowAsAction()} on the {@link
+android:showAsAction="ifRoom"} for the {@code <item>} element. This way, the menu item appears
+in the Action Bar for quick access only if there is room available for it. If there's not
+enough room, the item is placed the overflow menu (revealed by the menu icon on the right side
+of the Action Bar).</p>
+
+<p>You can also declare a menu item to appear as an action item from your application code, by
+calling {@link android.view.MenuItem#setShowAsAction setShowAsAction()} on the {@link
android.view.MenuItem} and passing {@link android.view.MenuItem#SHOW_AS_ACTION_IF_ROOM}.</p>
-<p>If your item supplies both a title and an icon, then the action item shows only
-the icon by defult. If you want to include the text with the action item, add the <em>with text</em>
-flag—in XML, add {@code withText} to the {@code android:showAsAction} attribute or, in
+<p>If your menu item supplies both a title and an icon, then the action item shows only
+the icon by defult. If you want to include the text with the action item, add the "with
+text" flag: in XML, add {@code withText} to the {@code android:showAsAction} attribute or, in
your application code, use the {@link android.view.MenuItem#SHOW_AS_ACTION_WITH_TEXT} flag when
-calling {@link android.view.MenuItem#setShowAsAction setShowAsAction()}. Figure 2 shows a screenshot
-of an Action Bar with two action items that include text.</p>
+calling {@link android.view.MenuItem#setShowAsAction setShowAsAction()}. Figure 2 shows an Action
+Bar that has two action items with text and the icon for the overflow menu.</p>
<p>Here's an example of how you can declare a menu item as an action item in a <a
href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a> file:</p>
@@ -149,32 +187,54 @@
item appears as an action item, it includes the title text along with the icon.</p>
<p>A menu item placed in the Action Bar triggers the same callback methods as other items in the
-Options Menu. When the user selects an item in the Action Bar, your activity receives a call to
+Options Menu. When the user selects an action item, your activity receives a call to
{@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}, passing the
-item ID. (If you added the item from a fragment, then the respective {@link
-android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method is called
-for that fragment.)</p>
+item ID.</p>
-<p class="note"><strong>Note:</strong> Menu items that appear in the Overflow Menu (not as action
-items) also show an icon, so it's best if you provide an icon for every menu item.</p>
+<p class="note"><strong>Note:</strong> If you added the menu item from a fragment, then the
+respective {@link
+android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method is called
+for that fragment. However the activity gets a chance to handle it first, so the system calls {@link
+android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} on the activity
+before calling the fragment.</p>
<p>You can also declare an item to <em>always</em> appear as an action item, but you should avoid
-doing so. Most of the time, there will be enough room for several action items and they will appear
-in the order you declare them. If you set items to always appear as action
-items (instead of <em>if room</em>), then they are added without discrimination and there is a risk
-that they will collide with other elements in the Action Bar, such as tabs or custom views.</p>
+doing so, because it can create a cluttered UI if there are too many action items and they might
+collide with other elements in the Action Bar.</p>
<p>For more information about menus, see the <a
href="{@docRoot}guide/topics/ui/menus.html#options-menu">Creating Menus</a> developer guide.</p>
-<h3 id="Home">Using the application icon as an action item</h3>
+<h3 id="Home">Using the app icon as an action item</h3>
-<p>By default, the application icon appears in the Action Bar on the left side, but does nothing
-when tapped. To use the application icon as an action item when tapped, you simply need to add a
-condition to your {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method
-that performs an action when the {@link android.view.MenuItem} ID is {@code android.R.id.home}.
-This ID is delivered every time the user taps the application icon.</p>
+<p>By default, your application icon appears in the Action Bar on the left side. It also responds
+to user interaction (when the user taps it, it visually responds the same way action
+items do) and it's your responsibility to do something when the user taps it.</p>
+
+<img src="{@docRoot}images/ui/actionbar.png" height="36" alt="" />
+<p class="img-caption"><strong>Figure 3.</strong> Email's Action Bar, with the
+application icon on the left.</p>
+
+<p>The normal behavior should be for your application to return to the "home" activity or the
+initial state (such as when the activity hasn't changed, but fragments have changed) when the user
+taps the icon. If the user is already at home or the initial state, then you don't need to do
+anything.</p>
+
+<p>When the user taps the icon, the system calls your activity's {@link
+android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method with the {@code
+android.R.id.home} ID. So, you need to add a condition to your {@link
+android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} method to listen for {@code
+android.R.id.home} and perform the appropriate action, such as start the home activity or pop recent
+fragment transactions off the stack.</p>
+
+<p>If you respond to the application icon by returning to the home activity, you should include
+the {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag in the {@link
+android.content.Intent}. With this flag, if the activity you're starting already exists in the
+current task, then all activities on top of it are destroyed and it is brought to the front.
+You should favor this approach, because going "home" is an action that's equivalent to "going
+back" and you should usually not create a new instance of the home activity. Otherwise, you
+might end up with a long stack of activities in the current task.</p>
<p>For example, here's an implementation of {@link android.app.Activity#onOptionsItemSelected
onOptionsItemSelected()} that returns to the application's "home" activity:</p>
@@ -186,97 +246,126 @@
case android.R.id.home:
// app icon in Action Bar clicked; go home
Intent intent = new Intent(this, HomeActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
- break;
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
}
- return super.onOptionsItemSelected(item);
}
</pre>
+
+
+
+<h4>Using the app icon to navigate "up"</h4>
+
<div class="figure" style="width:144px">
<img src="{@docRoot}images/ui/actionbar-logo.png" height="140" alt="" />
- <p class="img-caption"><strong>Figure 3.</strong> The standard icon for the Email application
-(top) and the "up navigation" icon (bottom).</p>
+ <p class="img-caption"><strong>Figure 4.</strong> The standard icon for the Email application
+(top) and the "up" icon (bottom).</p>
</div>
-<p>You can also use the application icon to provide "up" navigation. The way you handle the event
-when a user taps the icon is the same, but if the user experience for the event is to <em>navigate
-up to the parent activity</em>, then you should indicate this behavior by setting the
-Action Bar to "show home as up." You can do so by calling {@link
-android.app.ActionBar#setDisplayOptions setDisplayOptions()} on your activity's {@link
-android.app.ActionBar}, and passing the {@link
-android.app.ActionBar#DISPLAY_HOME_AS_UP} display option.</p>
+<p>You can also use the application icon to provide "up" navigation for the user. This is especially
+useful when your application is composed of activities that generally appear in a certain order and
+you want to facilitate the ability for the user to navigate up the activity hierarchy
+(regardless of how they entered the current activity).</p>
-<p>To get the {@link android.app.ActionBar}, call {@link android.app.Activity#getActionBar} from
-your {@link android.app.Activity} during {@link android.app.Activity#onCreate onCreate()} (but be
-sure you do so <em>after</em> you've called {@link android.app.Activity#setContentView
-setContentView()}).</p>
+<p>The way you respond to this event is the same as when navigating home (as
+discussed above, except you start a different activity, based on the current activity). All you
+need to do to indicate to the user that the behavior is different is set the Action Bar to "show
+home as up." You can do so by calling {@link android.app.ActionBar#setDisplayHomeAsUpEnabled
+setDisplayHomeAsUpEnabled(true)} on your activity's {@link android.app.ActionBar}. When you do, the
+system draws your application icon with an arrow indicating the up behavior, as shown in figure
+4.</p>
-<p>For example, here's how you can change the Action Bar display mode to show the application
-icon as an "up" action:</p>
+<p>For example, here's how you can show the application icon as an "up" action:</p>
<pre>
@Override
protected void onStart() {
- super.onStart();
- ActionBar actionBar = this.getActionBar();
- actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP);
+ super.onStart();
+ ActionBar actionBar = this.getActionBar();
+ actionBar.setDisplayHomeAsUpEnabled(true);
}
</pre>
-<p class="caution"><strong>Caution:</strong> If your activity does not have an Action Bar (if you
-did not set the theme of your activity or application to the holographic or Action Bar theme), then
-{@link android.app.Activity#getActionBar} returns null.</p>
+<p>Then, your activity should respond to the user tapping the icon, from the {@link
+android.app.Activity#onOptionsItemSelected
+onOptionsItemSelected()}, by listening for the {@code android.R.id.home} ID (as shown above). In
+this case, when navigating up, it's even more important that you use the {@link
+android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} flag in the {@link android.content.Intent}, so that
+you don't create a new instance of the parent activity if one already exists.</p>
+
<h2 id="ActionView">Adding an Action View</h2>
-<div class="figure" style="width:281px">
+<div class="figure" style="width:429px">
<img src="{@docRoot}images/ui/actionbar-actionview.png" alt="" />
- <p class="img-caption"><strong>Figure 4.</strong> An action view with a search widget.</p>
+ <p class="img-caption"><strong>Figure 5.</strong> An action view with a {@link
+android.widget.SearchView} widget.</p>
</div>
-<p>An action view is a customized view you can specify for an item in your Options Menu, to
-display in the Action Bar when the item is included as an action item. For example, you can
-include a menu item for "Search", which appears and behaves as a normal menu item in the Overflow
-Menu, but, when set as an action item, it provides an action view that is a {@link
-android.widget.SearchView}, so the user can initiate a search directly from the Action Bar.
-Figure 4 shows an example of this, in which a menu item for search provides an action view
-using the {@link android.widget.SearchView} widget.</p>
+<p>An action view is a widget that appears in the Action Bar as a substitute for an action
+item. For example, if you have an item in the Options Menu for "Search", you can add an action view
+for the item that provides a {@link android.widget.SearchView} widget in the Action Bar whenever
+the item is enabled as an action item.</p>
+
+<p>When adding an action view for a menu item, it's important that you still allow the item to
+behave as a normal menu item when it does not appear in the Action Bar. For example, a menu item to
+perform a search should, by default, bring up the <a
+href="{@docRoot}guide/topics/search/search-dialog.html">search dialog</a>, but if the item is
+placed in the Action Bar, the action view appears with a {@link android.widget.SearchView}
+widget. Figure 4 shows an example of the {@link android.widget.SearchView} widget in an action
+view.</p>
<p>The best way to declare an action view for an item is in your <a
href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, using the {@code
-android:actionLayout} or {@code android:actionViewClass} attribute.</p>
+android:actionLayout} or {@code android:actionViewClass} attribute:</p>
<ul>
<li>The value for {@code android:actionLayout} must be a resource pointer to a layout file.
For example:
<pre>
-<item android:id="@+id/menu_search"
- android:title="Search"
- android:icon="@drawable/ic_menu_search"
- android:showAsAction="ifRoom"
- <b>android:actionLayout="@layout/searchview"</b> />
-</pre></li>
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_search"
+ android:title="Search"
+ android:icon="@drawable/ic_menu_search"
+ android:showAsAction="ifRoom"
+ <b>android:actionLayout="@layout/searchview"</b> />
+</menu>
+</pre>
+</li>
+
<li>The value for {@code android:actionViewClass} must be a fully-qualified class name for
the {@link android.view.View} you want to use. For example:
<pre>
-<item android:id="@+id/menu_search"
- android:title="Search"
- android:icon="@drawable/ic_menu_search"
- android:showAsAction="ifRoom"
- <b>android:actionViewClass="android.widget.SearchView"</b> />
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_search"
+ android:title="Search"
+ android:icon="@drawable/ic_menu_search"
+ android:showAsAction="ifRoom"
+ <b>android:actionViewClass="android.widget.SearchView"</b> />
+</menu>
</pre></li>
</ul>
-<p>Now, when the menu item is displayed as an action item, it's action view appears instead of
-the item's traditional icon and/or text. Yet, if for some reason the item does not appear in the
-Action Bar, then it behaves like a normal menu item in the Overflow Menu and you must respond
-accordingly when the user taps it, from the {@link android.app.Activity#onOptionsItemSelected
-onOptionsItemSelected()} callback.</p>
+<p class="note">You must include {@code android:showAsAction="ifRoom"} in order for the item to
+appear as an action view when room is available. If necessary, however, you can force the item to
+always appear as an action view by setting {@code android:showAsAction} to {@code "always"}.</p>
-<p>When the activity first starts, the system populates the Action Bar and Overflow Menu by calling
+<p>Now, when the menu item is displayed as an action item, it's action view appears instead of
+the icon and/or title text. However, if there's not enough room in the Action Bar, the item appears
+in the overflow menu as a normal menu item and you must respond to it from the {@link
+android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} callback method. (For a
+guide to providing search functionality, see the <a
+href="{@docRoot}gudie/topics/search/index.html">Search</a> documentation.)</p>
+
+<p>When the activity first starts, the system populates the Action Bar and overflow menu by calling
{@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()}.
After you've inflated your menu in this method, you can acquire elements in an action view
(perhaps in order to attach listeners) by calling {@link android.view.Menu#findItem
@@ -300,19 +389,21 @@
+
<h2 id="Tabs">Adding Tabs</h2>
+
+<div class="figure" style="width:504px">
+ <img src="{@docRoot}images/ui/actionbar-tabs.png" alt="" />
+ <p class="img-caption"><strong>Figure 6.</strong> Screenshot of tabs in the
+Action Bar, from the <a
+href="{@docRoot}resources/samples/Honeycomb-Gallery/index.html">Honeycomb Gallery</a> sample
+application.</p>
+</div>
+
<p>The Action Bar can display tabs that allow the user navigate between different fragments in the
activity. Each tab can include a title and/or an icon.</p>
-<!--
-<div class="figure" style="width:300px">
- <img src="{@docRoot}images/ui/actionbar-tabs.png" alt="" />
- <p class="img-caption"><strong>Figure 5.</strong> Screenshot of tabs in the
-Action Bar.</p>
-</div>
--->
-
<p>To begin, your layout must include a {@link android.view.View} in which each {@link
android.app.Fragment} associated with a tab is displayed. Be sure the view has an ID that you
can use to reference it from your code.</p>
@@ -381,7 +472,7 @@
</li>
<li>Add each {@link android.app.ActionBar.Tab} to the Action Bar by calling {@link
android.app.ActionBar#addTab addTab()} on the {@link android.app.ActionBar} and passing the
-{@link android.app.ActionBar.Tab}.<>
+{@link android.app.ActionBar.Tab}.</li>
</ol>
<p>For example, the following code combines steps 2 - 5 to create two tabs and add them to
the Action Bar:</p>
@@ -395,7 +486,7 @@
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// remove the activity title to make space for tabs
- actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
+ actionBar.setDisplayShowTitleEnabled(false);
// instantiate fragment for the tab
Fragment artistsFragment = new ArtistsFragment();
@@ -418,9 +509,10 @@
selected), you should remove that fragment from the layout, using {@link
android.app.FragmentTransaction#remove remove()}.</p>
-<p class="note"><strong>Note:</strong> You <strong>do not</strong> need
-to call {@link android.app.FragmentTransaction#commit} for these transactions. You also
-<strong>cannot</strong> add these fragment transactions to the back stack.</p>
+<p class="caution"><strong>Caution:</strong> You <strong>must not</strong> call {@link
+android.app.FragmentTransaction#commit} for these transactions—the system calls it for you
+and it may throw an exception if you call it yourself. You also <strong>cannot</strong> add these
+fragment transactions to the back stack.</p>
<p>If your activity is stopped, you should retain the currently selected tab with the saved state so
that when the user returns to your application, you can open the tab. When it's time to save the
@@ -436,6 +528,7 @@
+
<h2 id="Dropdown">Adding Drop-down Navigation</h2>
<p>As another mode of navigation within your activity, you can provide a drop-down list in the
@@ -450,23 +543,25 @@
</div>
-->
-<p>Here's a quick list of what you must do to enable drop-down navigation:</p>
+<p>Here's a quick list of steps to enable drop-down navigation:</p>
<ol>
<li>Create a {@link android.widget.SpinnerAdapter} that provides the
-list of selectable items for the list and the layout to use when drawing each item in the list.</li>
+list of selectable items for the drop-down and the layout to use when drawing each item in the
+list.</li>
<li>Implement {@link android.app.ActionBar.OnNavigationListener} to define the behavior when the
user selects an item from the list.</li>
- <li>Turn on navigation mode for the Action Bar with {@link
+ <li>Enable navigation mode for the Action Bar with {@link
android.app.ActionBar#setNavigationMode setNavigationMode()}. For example:
<pre>
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
</pre>
- <p>You should perform this during your activity's {@link android.app.Activity#onCreate
+ <p class="note"><strong>Note:</strong> You should perform this during your activity's {@link
+android.app.Activity#onCreate
onCreate()} method.</p>
</li>
- <li>Following that, set the callback for your drop-down list with {@link
+ <li>Then, set the callback for the drop-down list with {@link
android.app.ActionBar#setListNavigationCallbacks setListNavigationCallbacks()}. For example:
<pre>
actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);
@@ -476,37 +571,45 @@
</li>
</ol>
-<p>That's the basic setup. The {@link android.widget.SpinnerAdapter} and {@link
-android.app.ActionBar.OnNavigationListener} is where most of the work is done. There are many ways
-you can implement these to define the functionality for your drop-down navigation. Implementing
-various types of {@link android.widget.SpinnerAdapter} is beyond the scope of this
-document—you should refer to the class refrence for more information about implementing it or
-extending an existing implementation. However, below is a simple example for a {@link
-android.widget.SpinnerAdapter} and {@link android.app.ActionBar.OnNavigationListener} to get you
-started.</p>
+<p>That's the basic setup. However, implementing the {@link android.widget.SpinnerAdapter} and
+{@link android.app.ActionBar.OnNavigationListener} is where most of the work is done. There are many
+ways you can implement these to define the functionality for your drop-down navigation and
+implementing various types of {@link android.widget.SpinnerAdapter} is beyond the scope of this
+document (you should refer to the {@link android.widget.SpinnerAdapter} class reference for more
+information). However, below is a simple example for a {@link android.widget.SpinnerAdapter} and
+{@link android.app.ActionBar.OnNavigationListener} to get you started (click the title to
+reveal the sample).</p>
-<h3 id="Spinner">Example: simple SpinnerAdapter</h3>
-<p>{@link android.widget.SpinnerAdapter} is an interface that you can implement to provide
-content for the list and is where your implementation for the drop-down list can be heavily
-customized. Android includes some useful implementations that you can extend, such as {@link
-android.widget.ArrayAdapter} and {@link
+<div class="toggle-content closed">
+
+ <h3 id="Spinner"><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt="" />
+ Example SpinnerAdapter and OnNavigationListener
+ </a></h3>
+
+ <div class="toggle-content-toggleme">
+
+<p>{@link android.widget.SpinnerAdapter} is an adapter that provides data for a spinner widget,
+such as the drop-down list in the Action Bar. {@link android.widget.SpinnerAdapter} is an interface
+that you can implement, but Android includes some useful implementations that you can extend, such
+as {@link android.widget.ArrayAdapter} and {@link
android.widget.SimpleCursorAdapter}. For example, here's an easy way to create a {@link
-android.widget.SpinnerAdapter} with {@link android.widget.ArrayAdapter}, using a string array
-from resources:</p>
+android.widget.SpinnerAdapter} by using {@link android.widget.ArrayAdapter} implementation, which
+uses a string array as the data source:</p>
<pre>
SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list,
android.R.layout.simple_spinner_dropdown_item);
</pre>
-<p>This is now ready to be given to {@link
-android.app.ActionBar#setListNavigationCallbacks setListNavigationCallbacks()}, in step 4 from
-above.</p>
+<p>The {@link android.widget.ArrayAdapter#createFromResource createFromResource()} method takes
+three parameters: the application {@link android.content.Context}, the resource ID for the string
+array, and the layout to use for each list item.</p>
<p>A <a href="{@docRoot}guide/topics/resources/string-resource.html#StringArray">string array</a>
-defined as a resource looks like this:</p>
+defined in a resource looks like this:</p>
<pre>
<?xml version="1.0" encoding="utf-8"?>
@@ -519,21 +622,26 @@
</pre>
</pre>
+<p>The {@link android.widget.ArrayAdapter} returned by {@link
+android.widget.ArrayAdapter#createFromResource createFromResource()} is complete and ready for you
+to pass it to {@link android.app.ActionBar#setListNavigationCallbacks setListNavigationCallbacks()}
+(in step 4 from above). Before you do, though, you need to create the {@link
+android.app.ActionBar.OnNavigationListener OnNavigationListener}.</p>
-<h3 id="OnNavigationListener">Example: simple OnNavigationListener</h3>
<p>Your implementation of {@link android.app.ActionBar.OnNavigationListener} is where you handle
fragment changes or other modifications to your activity when the user selects an item from the
-drop-down list. There's only one callback method to implement: {@link
+drop-down list. There's only one callback method to implement in the listener: {@link
android.app.ActionBar.OnNavigationListener#onNavigationItemSelected onNavigationItemSelected()}.</p>
<p>The {@link
android.app.ActionBar.OnNavigationListener#onNavigationItemSelected onNavigationItemSelected()}
-method receives the position of the item in the list and an item ID provided by the {@link
+method receives the position of the item in the list and a unique item ID provided by the {@link
android.widget.SpinnerAdapter}.</p>
<p>Here's an example that instantiates an anonymous implementation of {@link
-android.app.ActionBar.OnNavigationListener}, which inserts a {@link android.app.Fragment} into the
+android.app.ActionBar.OnNavigationListener OnNavigationListener}, which inserts a {@link
+android.app.Fragment} into the
layout container identified by {@code R.id.fragment_container}:</p>
<pre>
@@ -556,13 +664,18 @@
};
</pre>
-<p>This instance of {@link android.app.ActionBar.OnNavigationListener} can be given to {@link
-android.app.ActionBar#setListNavigationCallbacks setListNavigationCallbacks()}, in step 4 from
-above.</p>
+<p>This instance of {@link android.app.ActionBar.OnNavigationListener OnNavigationListener} is
+complete and you can now call {@link android.app.ActionBar#setListNavigationCallbacks
+setListNavigationCallbacks()} (in step 4), passing the {@link android.widget.ArrayAdapter} and this
+{@link android.app.ActionBar.OnNavigationListener OnNavigationListener}.</p>
-<p>In this example, the fragment added is given a tag that can uniquely identify the fragment.
-For this example, the {@code ListContentFragment} class used uses this tag as
-the text for a {@link android.widget.TextView} in the fragment's layout. Here's how it's done:</p>
+<p>In this example, when the user selects an item from the drop-down list, a fragment is added to
+the layout (replacing the current fragment in the {@code R.id.fragment_container} view). The
+fragment added is given a tag that uniquely identifies it, which is the same string used to
+identify the fragment in the drop-down list.</p>
+
+<p>Here's a look at the {@code ListContentFragment} class that defines each fragment in this
+example:</p>
<pre>
public class ListContentFragment extends Fragment {
@@ -588,6 +701,150 @@
}
</pre>
+ </div><!-- end toggle-content-toggleme -->
+
+</div><!-- end toggle-content -->
+
+
+
+
+
+<h2 id="Style">Styling the Action Bar</h2>
+
+<p>The Action Bar is the heading for your application and a primary interaction point for users,
+so you might want to modify some of its design in order to make it feel more integrated with your
+application design. There are several ways you can do this if you wish.</p>
+
+<p>For simple modifications to the {@link android.app.ActionBar}, you can use the following
+methods:</p>
+
+<dl>
+ <dt>{@link android.app.ActionBar#setBackgroundDrawable setBackgroundDrawable()}</dt>
+ <dd>Sets a drawable to use as the Action Bar's background. The drawable should be a <a
+href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">Nine-patch</a> image, a <a
+href="{@docRoot}guide/topics/resources/drawable-resource.html#Shape">shape</a>, or a <a
+href="{@docRoot}guide/topics/resources/more-resources.html#Color">solid color</a>, so the system can
+resize the drawable based on the size of the Action Bar (you should <em>not</em> use a fixed-size
+bitmap image).</dd>
+
+ <dt>{@link android.app.ActionBar#setDisplayUseLogoEnabled setDisplayUseLogoEnabled()}</dt>
+ <dd>Enables the use of an alternative image (a "logo") in the Action Bar, instead of the default
+application icon. A logo is often a wider, more detailed image that represents the application.
+When this is enabled, the system uses the logo image defined for the application (or the
+individual activity) in the manifest file, with the <a
+href="{@docRoot}guide/topics/manifest/application-element.html#logo">{@code android:logo}</a>
+attribute. The logo will be resized as necessary to fit the height of the Action Bar. (Best
+practice is to design the logo at the same size as your application icon.)</dd>
+</dl>
+
+
+<p>For more complex customizations, you can use Android's <a
+href="{@docRoot}guide/topics/ui/themes.html">style and theme</a> framework to restyle your Action
+Bar in several ways.</p>
+
+<p>The Action Bar has two standard themes, "dark" and "light". The dark theme is applied with
+the default holographic theme, as specified by the {@link android.R.style#Theme_Holo Theme.Holo}
+theme. If you want a white background with dark text, instead, you can apply the {@link
+android.R.style#Theme_Holo_Light Theme.Holo.Light} theme to the activity in the manifest file. For
+example:</p>
+
+<pre>
+<activity android:name=".ExampleActivity"
+ android:theme="@android:style/Theme.Holo.Light" />
+</pre>
+
+<p>For more control, you can override either the {@link android.R.style#Theme_Holo
+Theme.Holo} or {@link android.R.style#Theme_Holo_Light Theme.Holo.Light} theme and apply custom
+styles to certain aspects of the Action Bar. Some of the Action Bar properties you can customize
+include the following:</p>
+
+<dl>
+ <dt>{@link android.R.styleable#Theme_actionBarTabStyle
+ android:actionBarTabStyle}</dt>
+ <dd>Style for tabs in the Action Bar.</dd>
+
+ <dt>{@link android.R.styleable#Theme_actionBarTabBarStyle
+ android:actionBarTabBarStyle}</dt>
+ <dd>Style for the bar that appears below tabs in the Action Bar.</dd>
+
+ <dt>{@link android.R.styleable#Theme_actionBarTabTextStyle
+ android:actionBarTabTextStyle}</dt>
+ <dd>Style for the text in the tabs.</dd>
+
+ <dt>{@link android.R.styleable#Theme_actionDropDownStyle
+ android:actionDropDownStyle}</dt>
+ <dd>Style for the drop-down list used for the overflow menu and drop-down navigation.</dd>
+
+ <dt>{@link android.R.styleable#Theme_actionButtonStyle
+ android:actionButtonStyle}</dt>
+ <dd>Style for the background image used for buttons in the Action Bar.</dd>
+
+</dl>
+
+<p>For example, here's a resource file that defines a custom theme for the Action Bar, based on
+the standard {@link android.R.style#Theme_Holo Theme.Holo} theme:</p>
+
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- the theme applied to the application or activity -->
+ <style name="CustomActionBar" parent="android:style/Theme.Holo.Light">
+ <item name="android:actionBarTabTextStyle">@style/customActionBarTabTextStyle</item>
+ <item name="android:actionBarTabStyle">@style/customActionBarTabStyle</item>
+ <item name="android:actionBarTabBarStyle">@style/customActionBarTabBarStyle</item>
+ </style>
+
+ <!-- style for the tab text -->
+ <style name="customActionBarTabTextStyle">
+ <item name="android:textColor">#2966c2</item>
+ <item name="android:textSize">20sp</item>
+ <item name="android:typeface">sans</item>
+ </style>
+
+ <!-- style for the tabs -->
+ <style name="customActionBarTabStyle">
+ <item name="android:background">@drawable/actionbar_tab_bg</item>
+ <item name="android:paddingLeft">20dp</item>
+ <item name="android:paddingRight">20dp</item>
+ </style>
+
+ <!-- style for the tab bar -->
+ <style name="customActionBarTabBarStyle">
+ <item name="android:background">@drawable/actionbar_tab_bar</item>
+ </style>
+</resources>
+</pre>
+
+<p class="note"><strong>Note:</strong> In order for the tab background image to change,
+depending on the current tab state (selected, pressed, unselected), the drawable resource used
+must be a <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state
+list drawable</a>. Also be certain that your theme declares a parent theme, from which it
+inherits all styles not explicitly declared in your theme.</p>
+
+<p>You can apply your custom theme to the entire application or to individual activities in your
+manifest file, like this:</p>
+
+<pre>
+<application android:theme="@style/CustomActionBar"
+ ... />
+</pre>
+
+<p>Additionally, if you want to create a custom theme for your activity that removes the Action
+Bar completely, use the following style attributes:</p>
+
+<dl>
+ <dt>{@link android.R.styleable#Theme_windowActionBar
+ android:windowActionBar}</dt>
+ <dd>Set this style property {@code false} to remove the Action Bar.</dd>
+
+ <dt>{@link android.R.styleable#Theme_windowNoTitle
+ android:windowNoTitle}</dt>
+ <dd>Set this style property {@code true} to also remove the traditional title bar.</dd>
+</dl>
+
+<p>For more information about using themes in your application, read <a
+href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>.</p>
+
diff --git a/docs/html/images/ui/actionbar-actionview.png b/docs/html/images/ui/actionbar-actionview.png
index 30edca0..cc18f9b 100644
--- a/docs/html/images/ui/actionbar-actionview.png
+++ b/docs/html/images/ui/actionbar-actionview.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-item-withtext.png b/docs/html/images/ui/actionbar-item-withtext.png
index 98b5f84..61742d3 100644
--- a/docs/html/images/ui/actionbar-item-withtext.png
+++ b/docs/html/images/ui/actionbar-item-withtext.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-logo.png b/docs/html/images/ui/actionbar-logo.png
index 481ed2c..df914bc 100644
--- a/docs/html/images/ui/actionbar-logo.png
+++ b/docs/html/images/ui/actionbar-logo.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar-tabs.png b/docs/html/images/ui/actionbar-tabs.png
new file mode 100644
index 0000000..9d36db6
--- /dev/null
+++ b/docs/html/images/ui/actionbar-tabs.png
Binary files differ
diff --git a/docs/html/images/ui/actionbar.png b/docs/html/images/ui/actionbar.png
index 4fc871c..dcd8449 100644
--- a/docs/html/images/ui/actionbar.png
+++ b/docs/html/images/ui/actionbar.png
Binary files differ
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index a773007..c7ae2cf 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -464,8 +464,24 @@
Rect srcR = new Rect(x, y, x + width, y + height);
RectF dstR = new RectF(0, 0, width, height);
- final Config newConfig = source.getConfig() == Config.ARGB_8888 ||
- source.getConfig() == Config.ARGB_4444 ? Config.ARGB_8888 : Config.RGB_565;
+ Config newConfig = Config.ARGB_8888;
+ final Config config = source.getConfig();
+ // GIF files generate null configs, assume ARGB_8888
+ if (config != null) {
+ switch (config) {
+ case RGB_565:
+ newConfig = Config.RGB_565;
+ break;
+ case ALPHA_8:
+ newConfig = Config.ALPHA_8;
+ break;
+ case ARGB_4444:
+ case ARGB_8888:
+ default:
+ newConfig = Config.ARGB_8888;
+ break;
+ }
+ }
if (m == null || m.isIdentity()) {
bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index 77d37f1..168310c 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -72,6 +72,12 @@
virtual status_t setCrop(const Rect& reg) = 0;
virtual status_t setTransform(uint32_t transform) = 0;
+
+ // getAllocator retrieves the binder object that must be referenced as long
+ // as the GraphicBuffers dequeued from this ISurfaceTexture are referenced.
+ // Holding this binder reference prevents SurfaceFlinger from freeing the
+ // buffers before the client is done with them.
+ virtual sp<IBinder> getAllocator() = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 79c33f5..31615d0 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -101,6 +101,12 @@
// when a new frame becomes available.
void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
+ // getAllocator retrieves the binder object that must be referenced as long
+ // as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
+ // Holding this binder reference prevents SurfaceFlinger from freeing the
+ // buffers before the client is done with them.
+ sp<IBinder> getAllocator();
+
private:
// freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index dd1d490..ff2251d 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -83,6 +83,10 @@
// interactions with the server using this interface.
sp<ISurfaceTexture> mSurfaceTexture;
+ // mAllocator is the binder object that is referenced to prevent the
+ // dequeued buffers from being freed prematurely.
+ sp<IBinder> mAllocator;
+
// mSlots stores the buffers that have been allocated for each buffer slot.
// It is initialized to null pointers, and gets filled in with the result of
// ISurfaceTexture::requestBuffer when the client dequeues a buffer from a
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index 90bca3c..d661fd5 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -38,6 +38,7 @@
CANCEL_BUFFER,
SET_CROP,
SET_TRANSFORM,
+ GET_ALLOCATOR,
};
@@ -123,6 +124,13 @@
status_t result = reply.readInt32();
return result;
}
+
+ virtual sp<IBinder> getAllocator() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+ remote()->transact(GET_ALLOCATOR, data, &reply);
+ return reply.readStrongBinder();
+ }
};
IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
@@ -195,6 +203,12 @@
reply->writeInt32(result);
return NO_ERROR;
} break;
+ case GET_ALLOCATOR: {
+ CHECK_INTERFACE(ISurfaceTexture, data, reply);
+ sp<IBinder> result = getAllocator();
+ reply->writeStrongBinder(result);
+ return NO_ERROR;
+ } break;
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 1dadd53..3c4b565 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -304,6 +304,11 @@
mFrameAvailableListener = l;
}
+sp<IBinder> SurfaceTexture::getAllocator() {
+ LOGV("SurfaceTexture::getAllocator");
+ return mGraphicBufferAlloc->asBinder();
+}
+
void SurfaceTexture::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].mGraphicBuffer = 0;
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 50cbdb8..ee14ac9 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -25,8 +25,8 @@
SurfaceTextureClient::SurfaceTextureClient(
const sp<ISurfaceTexture>& surfaceTexture):
- mSurfaceTexture(surfaceTexture), mReqWidth(1), mReqHeight(1),
- mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
+ mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
+ mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
@@ -35,6 +35,9 @@
ANativeWindow::queueBuffer = queueBuffer;
ANativeWindow::query = query;
ANativeWindow::perform = perform;
+
+ // Get a reference to the allocator.
+ mAllocator = mSurfaceTexture->getAllocator();
}
int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) {
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 691f649..60ff0bf 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -16,8 +16,11 @@
#define LOG_TAG "OpenGLRenderer"
+#include <ui/Rect.h>
+
#include "LayerRenderer.h"
#include "Properties.h"
+#include "Rect.h"
namespace android {
namespace uirenderer {
@@ -29,13 +32,24 @@
void LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
-#if RENDER_LAYERS_AS_REGIONS
- mLayer->region.clear();
-#endif
-
glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
+#if RENDER_LAYERS_AS_REGIONS
+ Rect dirty(left, top, right, bottom);
+ if (dirty.isEmpty() || (dirty.left <= 0 && dirty.top <= 0 &&
+ dirty.right >= mLayer->width && dirty.bottom >= mLayer->height)) {
+ mLayer->region.clear();
+ dirty.set(0.0f, 0.0f, mLayer->width, mLayer->height);
+ } else {
+ dirty.intersect(0.0f, 0.0f, mLayer->width, mLayer->height);
+ android::Rect r(dirty.left, dirty.top, dirty.right, dirty.bottom);
+ mLayer->region.subtractSelf(r);
+ }
+
+ OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
+#else
OpenGLRenderer::prepareDirty(0.0f, 0.0f, mLayer->width, mLayer->height, opaque);
+#endif
}
void LayerRenderer::finish() {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2960395..90d6ea1 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -671,25 +671,7 @@
finishDrawTexture();
#if DEBUG_LAYERS_AS_REGIONS
- uint32_t colors[] = {
- 0x7fff0000, 0x7f00ff00,
- 0x7f0000ff, 0x7fff00ff,
- };
-
- int offset = 0;
- int32_t top = rects[0].top;
- int i = 0;
-
- for (size_t i = 0; i < count; i++) {
- if (top != rects[i].top) {
- offset ^= 0x2;
- top = rects[i].top;
- }
-
- Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
- drawColorRect(r.left, r.top, r.right, r.bottom, colors[offset + (i & 0x1)],
- SkXfermode::kSrcOver_Mode);
- }
+ drawRegionRects(layer->region);
#endif
layer->region.clear();
@@ -699,6 +681,32 @@
#endif
}
+void OpenGLRenderer::drawRegionRects(const Region& region) {
+#if DEBUG_LAYERS_AS_REGIONS
+ size_t count;
+ const android::Rect* rects = region.getArray(&count);
+
+ uint32_t colors[] = {
+ 0x7fff0000, 0x7f00ff00,
+ 0x7f0000ff, 0x7fff00ff,
+ };
+
+ int offset = 0;
+ int32_t top = rects[0].top;
+
+ for (size_t i = 0; i < count; i++) {
+ if (top != rects[i].top) {
+ offset ^= 0x2;
+ top = rects[i].top;
+ }
+
+ Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
+ drawColorRect(r.left, r.top, r.right, r.bottom, colors[offset + (i & 0x1)],
+ SkXfermode::kSrcOver_Mode);
+ }
+#endif
+}
+
void OpenGLRenderer::dirtyLayer(const float left, const float top,
const float right, const float bottom, const mat4 transform) {
#if RENDER_LAYERS_AS_REGIONS
@@ -1626,6 +1634,10 @@
GL_UNSIGNED_SHORT, layer->meshIndices);
finishDrawTexture();
+
+#if DEBUG_LAYERS_AS_REGIONS
+ drawRegionRects(layer->region);
+#endif
}
}
#else
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 64def03..7bbf034 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -455,6 +455,8 @@
void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
void finishDrawTexture();
+ void drawRegionRects(const Region& region);
+
/**
* Should be invoked every time the glScissor is modified.
*/
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index b8d1ca7..297c4df 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -23,6 +23,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -2064,6 +2065,20 @@
effectSettings.alphaBlendingFadeInTimePercent = 100;
effectSettings.alphaBlendingFadeOutTimePercent = 100;
effectSettings.framingBuffer = null;
+
+ /*
+ * Set the resized RGB file dimensions
+ */
+ effectSettings.width = overlay.getResizedRGBSizeWidth();
+ if(effectSettings.width == 0) {
+ effectSettings.width = bitmap.getWidth();
+ }
+
+ effectSettings.height = overlay.getResizedRGBSizeHeight();
+ if(effectSettings.height == 0) {
+ effectSettings.height = bitmap.getHeight();
+ }
+
}
effectSettings.topLeftX = 0;
@@ -2098,6 +2113,11 @@
return effectSettings;
}
+ /* get Video Editor aspect ratio */
+ int nativeHelperGetAspectRatio() {
+ return mVideoEditor.getAspectRatio();
+ }
+
/**
* Sets the audio regenerate flag
*
@@ -3039,6 +3059,8 @@
Log.e(TAG, "Runtime exception in nativeStartPreview");
throw ex;
}
+ } else {
+ throw new IllegalStateException("generatePreview is in progress");
}
}
@@ -3066,7 +3088,10 @@
long renderPreviewFrame(Surface surface, long time, int surfaceWidth,
int surfaceHeight, VideoEditor.OverlayData overlayData) {
if (mInvalidatePreviewArray) {
- throw new RuntimeException("Call generate preview first");
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Call generate preview first");
+ }
+ throw new IllegalStateException("Call generate preview first");
}
long timeMs = 0;
@@ -3894,6 +3919,27 @@
}
/**
+ * Tries to grab the semaphore with a specified time out which arbitrates access to the editor
+ *
+ * @param timeoutMs time out in ms.
+ *
+ * @return true if the semaphore is acquired, false otherwise
+ * @throws InterruptedException
+ */
+ boolean lock(long timeoutMs) throws InterruptedException {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "lock: grabbing semaphore with timeout " + timeoutMs, new Throwable());
+ }
+
+ boolean acquireSem = mLock.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "lock: grabbed semaphore status " + acquireSem);
+ }
+
+ return acquireSem;
+ }
+
+ /**
* Release the semaphore which arbitrates access to the editor
*/
void unlock() {
diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
index e3ef599..dfe0bae 100755
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ b/media/java/android/media/videoeditor/MediaItem.java
@@ -187,6 +187,10 @@
if (mEndTransition != null) {
mEndTransition.invalidate();
}
+
+ for (Overlay overlay : mOverlays) {
+ ((OverlayFrame)overlay).invalidateGeneratedFiles();
+ }
}
/**
diff --git a/media/java/android/media/videoeditor/OverlayFrame.java b/media/java/android/media/videoeditor/OverlayFrame.java
index 2bb9a1c..131f5f0 100755
--- a/media/java/android/media/videoeditor/OverlayFrame.java
+++ b/media/java/android/media/videoeditor/OverlayFrame.java
@@ -21,15 +21,19 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap.CompressFormat;
-
import java.io.DataOutputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap.CompressFormat;
+import android.util.Pair;
+
+
/**
* This class is used to overlay an image on top of a media item.
* {@hide}
@@ -46,6 +50,17 @@
private int mOFHeight;
/**
+ * resized RGB Image dimensions
+ */
+ private int mResizedRGBWidth;
+ private int mResizedRGBHeight;
+
+ /**
+ * The resize paint
+ */
+ private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+
+ /**
* An object of this type cannot be instantiated by using the default
* constructor
*/
@@ -74,6 +89,8 @@
mBitmap = bitmap;
mFilename = null;
mBitmapFileName = null;
+ mResizedRGBWidth = 0;
+ mResizedRGBHeight = 0;
}
/**
@@ -95,6 +112,8 @@
mBitmapFileName = filename;
mBitmap = BitmapFactory.decodeFile(mBitmapFileName);
mFilename = null;
+ mResizedRGBWidth = 0;
+ mResizedRGBHeight = 0;
}
/**
@@ -182,32 +201,23 @@
mOFHeight = mBitmap.getHeight();
mFilename = path + "/" + "Overlay" + getId() + ".rgb";
- if (!(new File(mFilename).exists())) {
- /**
- * Save the image to a file ; as a rgb
- */
- final FileOutputStream fl = new FileOutputStream(mFilename);
- final DataOutputStream dos = new DataOutputStream(fl);
- /**
- * populate the rgb file with bitmap data
- */
- final int [] framingBuffer = new int[mOFWidth];
- ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
- IntBuffer intBuffer;
+ /* resize and save rgb as per project aspect ratio */
+ MediaArtistNativeHelper nativeHelper = (super.getMediaItem()).getNativeContext();
- byte[] array = byteBuffer.array();
- int tmp = 0;
- while(tmp < mOFHeight) {
- mBitmap.getPixels(framingBuffer,0,mOFWidth,0,tmp,mOFWidth,1);
- intBuffer = byteBuffer.asIntBuffer();
- intBuffer.put(framingBuffer,0,mOFWidth);
- dos.write(array);
- tmp += 1;
- }
- fl.flush();
- fl.close();
- }
+ /* get height and width for story board aspect ratio */
+ final Pair<Integer, Integer> maxResolution;
+ final Pair<Integer, Integer>[] resolutions;
+ resolutions = MediaProperties.getSupportedResolutions(nativeHelper.nativeHelperGetAspectRatio());
+
+ // Get the highest resolution
+ maxResolution = resolutions[resolutions.length - 1];
+
+ /* Generate the rgb file with rendering mode */
+ generateOverlayWithRenderingMode (super.getMediaItem(), this,
+ maxResolution.second /* max Height */ ,
+ maxResolution.first /* max Width */);
+
return mFilename;
}
@@ -238,6 +248,30 @@
void setOverlayFrameWidth(int width) {
mOFWidth = width;
}
+
+ /*
+ * Set the resized RGB widht and height
+ */
+ void setResizedRGBSize(int width, int height) {
+ mResizedRGBWidth = width;
+ mResizedRGBHeight = height;
+ }
+
+ /*
+ * Get the resized RGB Height
+ */
+ int getResizedRGBSizeHeight() {
+ return mResizedRGBHeight;
+ }
+
+ /*
+ * Get the resized RGB Width
+ */
+ int getResizedRGBSizeWidth() {
+ return mResizedRGBWidth;
+ }
+
+
/**
* Delete the overlay files
*/
@@ -257,4 +291,174 @@
mBitmapFileName = null;
}
}
+
+ /**
+ * Delete the overlay related files
+ */
+ void invalidateGeneratedFiles() {
+ if (mFilename != null) {
+ new File(mFilename).delete();
+ mFilename = null;
+ }
+
+ if (mBitmapFileName != null) {
+ new File(mBitmapFileName).delete();
+ mBitmapFileName = null;
+ }
+ }
+
+ void generateOverlayWithRenderingMode (MediaItem mediaItemsList, OverlayFrame overlay, int height , int width)
+ throws FileNotFoundException, IOException {
+
+ final MediaItem t = mediaItemsList;
+
+ /* get the rendering mode */
+ int renderMode = t.getRenderingMode();
+
+ Bitmap overlayBitmap = ((OverlayFrame)overlay).getBitmap();
+
+ /*
+ * Check if the resize of Overlay is needed with rendering mode applied
+ * because of change in export dimensions
+ */
+ int resizedRGBFileHeight = ((OverlayFrame)overlay).getResizedRGBSizeHeight();
+ int resizedRGBFileWidth = ((OverlayFrame)overlay).getResizedRGBSizeWidth();
+
+ /* Get original bitmap width if it is not resized */
+ if(resizedRGBFileWidth == 0) {
+ resizedRGBFileWidth = overlayBitmap.getWidth();
+ }
+ /* Get original bitmap height if it is not resized */
+ if(resizedRGBFileHeight == 0) {
+ resizedRGBFileHeight = overlayBitmap.getHeight();
+ }
+
+ if (resizedRGBFileWidth != width || resizedRGBFileHeight != height
+ || (!(new File(((OverlayFrame)overlay).getFilename()).exists()))) {
+ /*
+ * Create the canvas bitmap
+ */
+ final Bitmap destBitmap = Bitmap.createBitmap((int)width,
+ (int)height,
+ Bitmap.Config.ARGB_8888);
+ final Canvas overlayCanvas = new Canvas(destBitmap);
+ final Rect destRect;
+ final Rect srcRect;
+
+ switch (renderMode) {
+ case MediaItem.RENDERING_MODE_STRETCH: {
+ destRect = new Rect(0, 0, overlayCanvas.getWidth(),
+ overlayCanvas.getHeight());
+ srcRect = new Rect(0, 0, overlayBitmap.getWidth(),
+ overlayBitmap.getHeight());
+ break;
+ }
+
+ case MediaItem.RENDERING_MODE_BLACK_BORDER: {
+ int left, right, top, bottom;
+ float aROverlayImage, aRCanvas;
+ aROverlayImage = (float)(overlayBitmap.getWidth()) /
+ (float)(overlayBitmap.getHeight());
+
+ aRCanvas = (float)(overlayCanvas.getWidth()) /
+ (float)(overlayCanvas.getHeight());
+
+ if (aROverlayImage > aRCanvas) {
+ int newHeight = ((overlayCanvas.getWidth() * overlayBitmap.getHeight())
+ / overlayBitmap.getWidth());
+ left = 0;
+ top = (overlayCanvas.getHeight() - newHeight) / 2;
+ right = overlayCanvas.getWidth();
+ bottom = top + newHeight;
+ } else {
+ int newWidth = ((overlayCanvas.getHeight() * overlayBitmap.getWidth())
+ / overlayBitmap.getHeight());
+ left = (overlayCanvas.getWidth() - newWidth) / 2;
+ top = 0;
+ right = left + newWidth;
+ bottom = overlayCanvas.getHeight();
+ }
+
+ destRect = new Rect(left, top, right, bottom);
+ srcRect = new Rect(0, 0, overlayBitmap.getWidth(), overlayBitmap.getHeight());
+ break;
+ }
+
+ case MediaItem.RENDERING_MODE_CROPPING: {
+ // Calculate the source rect
+ int left, right, top, bottom;
+ float aROverlayImage, aRCanvas;
+ aROverlayImage = (float)(overlayBitmap.getWidth()) /
+ (float)(overlayBitmap.getHeight());
+ aRCanvas = (float)(overlayCanvas.getWidth()) /
+ (float)(overlayCanvas.getHeight());
+ if (aROverlayImage < aRCanvas) {
+ int newHeight = ((overlayBitmap.getWidth() * overlayCanvas.getHeight())
+ / overlayCanvas.getWidth());
+
+ left = 0;
+ top = (overlayBitmap.getHeight() - newHeight) / 2;
+ right = overlayBitmap.getWidth();
+ bottom = top + newHeight;
+ } else {
+ int newWidth = ((overlayBitmap.getHeight() * overlayCanvas.getWidth())
+ / overlayCanvas.getHeight());
+ left = (overlayBitmap.getWidth() - newWidth) / 2;
+ top = 0;
+ right = left + newWidth;
+ bottom = overlayBitmap.getHeight();
+ }
+
+ srcRect = new Rect(left, top, right, bottom);
+ destRect = new Rect(0, 0, overlayCanvas.getWidth(), overlayCanvas.getHeight());
+ break;
+ }
+
+ default: {
+ throw new IllegalStateException("Rendering mode: " + renderMode);
+ }
+ }
+
+ overlayCanvas.drawBitmap(overlayBitmap, srcRect, destRect, sResizePaint);
+
+ /*
+ * Write to the dest file
+ */
+ String outFileName = ((OverlayFrame)overlay).getFilename();
+
+ /*
+ * Save the image to same rgb file
+ */
+ if (outFileName != null) {
+ new File(outFileName).delete();
+ }
+
+ final FileOutputStream fl = new FileOutputStream(outFileName);
+ final DataOutputStream dos = new DataOutputStream(fl);
+
+ /*
+ * Populate the rgb file with bitmap data
+ */
+ final int [] framingBuffer = new int[width];
+ ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
+ IntBuffer intBuffer;
+
+ byte[] array = byteBuffer.array();
+ int tmp = 0;
+ while(tmp < height) {
+ destBitmap.getPixels(framingBuffer,0,width,0,tmp,width,1);
+ intBuffer = byteBuffer.asIntBuffer();
+ intBuffer.put(framingBuffer,0,width);
+ dos.write(array);
+ tmp += 1;
+ }
+ fl.flush();
+ fl.close();
+
+ /*
+ * Set the resized RGB width and height
+ */
+ ((OverlayFrame)overlay).setResizedRGBSize(width, height);
+ }
+ }
}
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index b8c211e..27ab799 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -109,7 +109,10 @@
private static final String ATTR_OVERLAY_RGB_FILENAME = "overlay_rgb_filename";
private static final String ATTR_OVERLAY_FRAME_WIDTH = "overlay_frame_width";
private static final String ATTR_OVERLAY_FRAME_HEIGHT = "overlay_frame_height";
+ private static final String ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH = "resized_RGBframe_width";
+ private static final String ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT = "resized_RGBframe_height";
+ private static final int ENGINE_ACCESS_MAX_TIMEOUT_MS = 500;
/*
* Instance variables
*/
@@ -850,8 +853,10 @@
boolean semAcquireDone = false;
try {
- mMANativeHelper.lock();
- semAcquireDone = true;
+ semAcquireDone = mMANativeHelper.lock(ENGINE_ACCESS_MAX_TIMEOUT_MS);
+ if (semAcquireDone == false) {
+ throw new IllegalStateException("Timeout waiting for semaphore");
+ }
if (mMediaItems.size() > 0) {
final Rect frame = surfaceHolder.getSurfaceFrame();
@@ -860,14 +865,14 @@
} else {
result = 0;
}
- } catch (InterruptedException ex) {
- Log.e(TAG, "Sem acquire NOT successful in renderPreviewFrame");
+ } catch (InterruptedException ex) {
+ Log.w(TAG, "The thread was interrupted", new Throwable());
+ throw new IllegalStateException("The thread was interrupted");
} finally {
if (semAcquireDone) {
mMANativeHelper.unlock();
}
}
-Log.i("VE_IMPL","renderPreviewFrame <--");
return result;
}
@@ -1154,6 +1159,15 @@
((OverlayFrame)overlay).setOverlayFrameWidth(overlayFrameWidth);
((OverlayFrame)overlay).setOverlayFrameHeight(overlayFrameHeight);
+
+ final int resizedRGBFrameWidth =
+ Integer.parseInt(parser.getAttributeValue("",
+ ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH));
+ final int resizedRGBFrameHeight =
+ Integer.parseInt(parser.getAttributeValue("",
+ ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT));
+
+ ((OverlayFrame)overlay).setResizedRGBSize(resizedRGBFrameWidth, resizedRGBFrameHeight);
}
return overlay;
@@ -1340,6 +1354,11 @@
Integer.toString(overlayFrame.getOverlayFrameWidth()));
serializer.attribute("", ATTR_OVERLAY_FRAME_HEIGHT,
Integer.toString(overlayFrame.getOverlayFrameHeight()));
+ serializer.attribute("", ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH,
+ Integer.toString(overlayFrame.getResizedRGBSizeWidth()));
+ serializer.attribute("", ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT,
+ Integer.toString(overlayFrame.getResizedRGBSizeHeight()));
+
}
}
@@ -1519,9 +1538,22 @@
/**
* Invalidate all transitions
*/
+ mMANativeHelper.setGeneratePreview(true);
+
for (Transition transition : mTransitions) {
transition.invalidate();
}
+
+ final Iterator<MediaItem> it = mMediaItems.iterator();
+
+ while (it.hasNext()) {
+ final MediaItem t = it.next();
+ List<Overlay> overlayList = t.getAllOverlays();
+ for (Overlay overlay : overlayList) {
+
+ ((OverlayFrame)overlay).invalidateGeneratedFiles();
+ }
+ }
}
/*
@@ -1554,8 +1586,10 @@
boolean semAcquireDone = false;
try{
- mMANativeHelper.lock();
- semAcquireDone = true;
+ semAcquireDone = mMANativeHelper.lock(ENGINE_ACCESS_MAX_TIMEOUT_MS);
+ if (semAcquireDone == false) {
+ throw new IllegalStateException("Timeout waiting for semaphore");
+ }
if (mMediaItems.size() > 0) {
mMANativeHelper.previewStoryBoard(mMediaItems, mTransitions,
@@ -1567,17 +1601,9 @@
/**
* release on complete by calling stopPreview
*/
- } catch (InterruptedException ex) {
- Log.e(TAG, "Sem acquire NOT successful in startPreview");
- } catch (IllegalArgumentException ex) {
- Log.e(TAG, "Illegal Argument exception in do preview");
- throw ex;
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Illegal State exception in do preview");
- throw ex;
- } catch (RuntimeException ex) {
- Log.e(TAG, "Runtime exception in do preview");
- throw ex;
+ } catch (InterruptedException ex) {
+ Log.w(TAG, "The thread was interrupted", new Throwable());
+ throw new IllegalStateException("The thread was interrupted");
} finally {
if (semAcquireDone) {
mMANativeHelper.unlock();
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 221bfa1..c23169a 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -454,7 +454,7 @@
case MSG_TYPE_OVERLAY_CLEAR:
isSendProgress = false;
pContext->mOverlayFileName = NULL;
- LOGI("MSG_TYPE_OVERLAY_CLEAR");
+ LOGV("MSG_TYPE_OVERLAY_CLEAR");
//argc is not used
pContext->mIsUpdateOverlay = true;
break;
@@ -1102,7 +1102,7 @@
{
bool needToBeLoaded = true;
M4OSA_ERR result = M4NO_ERROR;
- M4MCS_Context mcsContext;
+ M4MCS_Context mcsContext = M4OSA_NULL;
M4OSA_Char* pInputFile = M4OSA_NULL;
M4OSA_Char* pOutputFile = M4OSA_NULL;
M4OSA_Char* pTempPath = M4OSA_NULL;
@@ -1126,6 +1126,9 @@
videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
(M4OSA_NULL == pOutputParams),
"not initialized");
+ if (needToBeLoaded == false) {
+ return M4ERR_ALLOC;
+ }
pEncodingParams = (M4MCS_EncodingParams *)M4OSA_malloc(
sizeof(M4MCS_EncodingParams),0x00,
@@ -1133,6 +1136,12 @@
videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
(M4OSA_NULL == pEncodingParams),
"not initialized");
+ if (needToBeLoaded == false) {
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ pEncodingParams = M4OSA_NULL;
+ return M4ERR_ALLOC;
+ }
+
// Initialize the MCS library.
result = M4MCS_init(&mcsContext, pContext->initParams.pFileReadPtr,
pContext->initParams.pFileWritePtr);
@@ -1141,6 +1150,14 @@
videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
(M4OSA_NULL == mcsContext),
"not initialized");
+ if(needToBeLoaded == false) {
+ M4OSA_free((M4OSA_MemAddr32)pOutputParams);
+ pOutputParams = M4OSA_NULL;
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ pEncodingParams = M4OSA_NULL;
+ return result;
+ }
+
// generate the path for temp 3gp output file
pTemp3gpFilePath = (M4OSA_Char*) M4OSA_malloc (
(M4OSA_chrLength((M4OSA_Char*)pContext->initParams.pTempPath)
@@ -1157,6 +1174,14 @@
M4OSA_chrNCat ( pTemp3gpFilePath , (M4OSA_Char*)TEMP_MCS_OUT_FILE_PATH,
M4OSA_chrLength ((M4OSA_Char*)TEMP_MCS_OUT_FILE_PATH));
}
+ else {
+ M4MCS_abort(mcsContext);
+ M4OSA_free((M4OSA_MemAddr32)pOutputParams);
+ pOutputParams = M4OSA_NULL;
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ pEncodingParams = M4OSA_NULL;
+ return M4ERR_ALLOC;
+ }
pInputFile = (M4OSA_Char *) infilePath; //pContext->mAudioSettings->pFile;
//Delete this file later
@@ -1177,6 +1202,16 @@
pOutputFile, pTempPath);
videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
(M4NO_ERROR != result), result);
+ if(needToBeLoaded == false) {
+ M4OSA_free((M4OSA_MemAddr32)pTemp3gpFilePath);
+ pTemp3gpFilePath = M4OSA_NULL;
+ M4MCS_abort(mcsContext);
+ M4OSA_free((M4OSA_MemAddr32)pOutputParams);
+ pOutputParams = M4OSA_NULL;
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ pEncodingParams = M4OSA_NULL;
+ return result;
+ }
pOutputParams->OutputFileType
= (M4VIDEOEDITING_FileType)M4VIDEOEDITING_kFileType_3GPP;
@@ -1217,7 +1252,16 @@
result = M4MCS_setOutputParams(mcsContext, pOutputParams);
videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
(M4NO_ERROR != result), result);
-
+ if (needToBeLoaded == false) {
+ M4OSA_free((M4OSA_MemAddr32)pTemp3gpFilePath);
+ pTemp3gpFilePath = M4OSA_NULL;
+ M4MCS_abort(mcsContext);
+ M4OSA_free((M4OSA_MemAddr32)pOutputParams);
+ pOutputParams = M4OSA_NULL;
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ pEncodingParams = M4OSA_NULL;
+ return result;
+ }
// Set the video bitrate.
pEncodingParams->OutputVideoBitrate =
(M4VIDEOEDITING_Bitrate)M4VIDEOEDITING_kUndefinedBitrate;
@@ -1238,12 +1282,32 @@
result = M4MCS_setEncodingParams(mcsContext, pEncodingParams);
videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
(M4NO_ERROR != result), result);
+ if (needToBeLoaded == false) {
+ M4OSA_free((M4OSA_MemAddr32)pTemp3gpFilePath);
+ pTemp3gpFilePath = M4OSA_NULL;
+ M4MCS_abort(mcsContext);
+ M4OSA_free((M4OSA_MemAddr32)pOutputParams);
+ pOutputParams = M4OSA_NULL;
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ pEncodingParams = M4OSA_NULL;
+ return result;
+ }
VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
"M4MCS_checkParamsAndStart()");
result = M4MCS_checkParamsAndStart(mcsContext);
videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
(M4NO_ERROR != result), result);
+ if (needToBeLoaded == false) {
+ M4OSA_free((M4OSA_MemAddr32)pTemp3gpFilePath);
+ pTemp3gpFilePath = M4OSA_NULL;
+ M4MCS_abort(mcsContext);
+ M4OSA_free((M4OSA_MemAddr32)pOutputParams);
+ pOutputParams = M4OSA_NULL;
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ pEncodingParams = M4OSA_NULL;
+ return result;
+ }
VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_step()");
@@ -1286,6 +1350,16 @@
videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
(M4MCS_WAR_TRANSCODING_DONE != result), result);
+ if (needToBeLoaded == false) {
+ M4OSA_free((M4OSA_MemAddr32)pTemp3gpFilePath);
+ pTemp3gpFilePath = M4OSA_NULL;
+ M4MCS_abort(mcsContext);
+ M4OSA_free((M4OSA_MemAddr32)pOutputParams);
+ pOutputParams = M4OSA_NULL;
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ pEncodingParams = M4OSA_NULL;
+ return result;
+ }
VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_abort()");
result = M4MCS_abort(mcsContext);
@@ -1296,9 +1370,15 @@
M4OSA_fileExtraDelete((const M4OSA_Char *) pTemp3gpFilePath);
VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_generateAudio() EXIT ");
- M4OSA_free((M4OSA_MemAddr32)pTemp3gpFilePath);
- M4OSA_free((M4OSA_MemAddr32)pOutputParams);
- M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ if (pTemp3gpFilePath != M4OSA_NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pTemp3gpFilePath);
+ }
+ if (pOutputParams != M4OSA_NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pOutputParams);
+ }
+ if(pEncodingParams != M4OSA_NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pEncodingParams);
+ }
return result;
}
@@ -1439,14 +1519,33 @@
videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
(pContext->state != ManualEditState_INITIALIZED),
"settings already loaded");
- // Retrieve the edit settings.
- if (pContext->pEditSettings != M4OSA_NULL) {
- videoEditClasses_freeEditSettings(&pContext->pEditSettings);
- pContext->pEditSettings = M4OSA_NULL;
+ if (needToBeLoaded) {
+ // Retrieve the edit settings.
+ if (pContext->pEditSettings != M4OSA_NULL) {
+ videoEditClasses_freeEditSettings(&pContext->pEditSettings);
+ pContext->pEditSettings = M4OSA_NULL;
+ }
+ videoEditClasses_getEditSettings(&needToBeLoaded, pEnv,
+ settings, &pContext->pEditSettings,false);
}
- videoEditClasses_getEditSettings(&needToBeLoaded, pEnv,
- settings, &pContext->pEditSettings,false);
}
+
+ if (needToBeLoaded == false) {
+ j = 0;
+ while (j < pContext->pEditSettings->nbEffects)
+ {
+ if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) {
+ if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer != M4OSA_NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pContext->pEditSettings->\
+ Effects[j].xVSS.pFramingBuffer);
+ pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer = M4OSA_NULL;
+ }
+ }
+ j++;
+ }
+ return;
+ }
+
M4OSA_TRACE1_0("videoEditorC_getEditSettings done");
pContext->previewFrameEditInfoId = pEnv->GetMethodID(engineClass,
@@ -1459,43 +1558,49 @@
if(mEditClazz == M4OSA_NULL)
{
M4OSA_TRACE1_0("cannot find object field for mEditClazz");
- return;
+ goto videoEditor_populateSettings_cleanup;
}
jclass mEffectsClazz = pEnv->FindClass(EFFECT_SETTINGS_CLASS_NAME);
if(mEffectsClazz == M4OSA_NULL)
{
M4OSA_TRACE1_0("cannot find object field for mEffectsClazz");
- return;
+ goto videoEditor_populateSettings_cleanup;
}
fid = pEnv->GetFieldID(mEditClazz,"effectSettingsArray", "[L"EFFECT_SETTINGS_CLASS_NAME";" );
if(fid == M4OSA_NULL)
{
M4OSA_TRACE1_0("cannot find field for effectSettingsArray Array");
- return;
+ goto videoEditor_populateSettings_cleanup;
}
effectSettingsArray = (jobjectArray)pEnv->GetObjectField(settings, fid);
if(effectSettingsArray == M4OSA_NULL)
{
M4OSA_TRACE1_0("cannot find object field for effectSettingsArray");
- return;
- }
- i = 0;
- j = 0;
- //int overlayIndex[pContext->pEditSettings->nbEffects];
- if ( pContext->pEditSettings->nbEffects )
- {
- pOverlayIndex
- = (int*) M4OSA_malloc(pContext->pEditSettings->nbEffects, 0,
- (M4OSA_Char*)"pOverlayIndex");
+ goto videoEditor_populateSettings_cleanup;
}
+ //int overlayIndex[pContext->pEditSettings->nbEffects];
+ if (pContext->pEditSettings->nbEffects > 0)
+ {
+ pOverlayIndex
+ = (int*) M4OSA_malloc(pContext->pEditSettings->nbEffects * sizeof(int), 0,
+ (M4OSA_Char*)"pOverlayIndex");
+ if (pOverlayIndex == M4OSA_NULL) {
+ videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
+ M4OSA_TRUE, M4ERR_ALLOC);
+ goto videoEditor_populateSettings_cleanup;
+ }
+ }
+
+ i = 0;
+ j = 0;
M4OSA_TRACE1_1("no of effects = %d",pContext->pEditSettings->nbEffects);
while (j < pContext->pEditSettings->nbEffects)
{
if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL)
{
pOverlayIndex[nbOverlays] = j;
- nbOverlays++;
+
M4xVSS_FramingStruct *aFramingCtx = M4OSA_NULL;
aFramingCtx
= (M4xVSS_FramingStruct*)M4OSA_malloc(sizeof(M4xVSS_FramingStruct), M4VS,
@@ -1503,7 +1608,11 @@
if (aFramingCtx == M4OSA_NULL)
{
M4OSA_TRACE1_0("Allocation error in videoEditor_populateSettings");
+ videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
+ M4OSA_TRUE, M4ERR_ALLOC);
+ goto videoEditor_populateSettings_cleanup;
}
+
aFramingCtx->pCurrent = M4OSA_NULL; /* Only used by the first element of the chain */
aFramingCtx->previousClipTime = -1;
aFramingCtx->FramingYuv = M4OSA_NULL;
@@ -1524,13 +1633,18 @@
aFramingCtx->width = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width;
aFramingCtx->height = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height;
-
result = M4xVSS_internalConvertARGB888toYUV420_FrammingEffect(pContext->engineContext,
&(pContext->pEditSettings->Effects[j]),aFramingCtx,
pContext->pEditSettings->Effects[j].xVSS.framingScaledSize);
- if (result != M4NO_ERROR)
- {
+ videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
+ (M4NO_ERROR != result), result);
+ if (needToBeLoaded == false) {
M4OSA_TRACE1_1("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect returned 0x%x", result);
+ if (aFramingCtx != M4OSA_NULL) {
+ M4OSA_free((M4OSA_MemAddr32)aFramingCtx);
+ aFramingCtx = M4OSA_NULL;
+ }
+ goto videoEditor_populateSettings_cleanup;
}
//framing buffers are resized to fit the output video resolution.
@@ -1539,7 +1653,6 @@
pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height =
aFramingCtx->FramingRgb->u_height;
-
VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "A framing Context aFramingCtx->width = %d",
aFramingCtx->FramingRgb->u_width);
@@ -1551,7 +1664,7 @@
height = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height;
//RGB 565
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_stride = width*2;
+ pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_stride = width * 2;
//for RGB565
pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_topleft = 0;
@@ -1559,6 +1672,13 @@
(M4VIFI_UInt8 *)M4OSA_malloc(width*height*2,
0x00,(M4OSA_Char *)"pac_data buffer");
+ if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->pac_data == M4OSA_NULL) {
+ M4OSA_TRACE1_0("Failed to allocate memory for framing buffer");
+ videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
+ M4OSA_TRUE, M4ERR_ALLOC);
+ goto videoEditor_populateSettings_cleanup;
+ }
+
M4OSA_memcpy((M4OSA_Int8 *)&pContext->pEditSettings->\
Effects[j].xVSS.pFramingBuffer->\
pac_data[0],(M4OSA_Int8 *)&aFramingCtx->FramingRgb->pac_data[0],(width*height*2));
@@ -1590,6 +1710,7 @@
M4OSA_free((M4OSA_MemAddr32)aFramingCtx);
aFramingCtx = M4OSA_NULL;
}
+ nbOverlays++;
}
j++;
}
@@ -1602,7 +1723,11 @@
videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
(M4OSA_NULL == properties),
"not initialized");
- getClipSetting(pEnv,properties, pContext->pEditSettings->pClipList[i]);
+ if (needToBeLoaded) {
+ getClipSetting(pEnv,properties, pContext->pEditSettings->pClipList[i]);
+ } else {
+ goto videoEditor_populateSettings_cleanup;
+ }
}
if (needToBeLoaded) {
@@ -1621,6 +1746,10 @@
(M4OSA_NULL == pContext->mAudioSettings),
"not initialized");
+ if (needToBeLoaded == false) {
+ goto videoEditor_populateSettings_cleanup;
+ }
+
fid = pEnv->GetFieldID(audioSettingClazz,"bRemoveOriginal","Z");
pContext->mAudioSettings->bRemoveOriginal = pEnv->GetIntField(audioSettingObject,fid);
M4OSA_TRACE1_1("bRemoveOriginal = %d",pContext->mAudioSettings->bRemoveOriginal);
@@ -1675,37 +1804,51 @@
M4OSA_TRACE1_1("file name = %s",pContext->mAudioSettings->pFile);
VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio() file name = %s",\
pContext->mAudioSettings->pFile);
+
fid = pEnv->GetFieldID(audioSettingClazz,"pcmFilePath","Ljava/lang/String;");
str = (jstring)pEnv->GetObjectField(audioSettingObject,fid);
+
pContext->mAudioSettings->pPCMFilePath =
(M4OSA_Char*)pEnv->GetStringUTFChars(str, M4OSA_NULL);
+
VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "pPCMFilePath -- %s ",\
pContext->mAudioSettings->pPCMFilePath);
+
fid = pEnv->GetFieldID(engineClass,"mRegenerateAudio","Z");
bool regenerateAudio = pEnv->GetBooleanField(thiz,fid);
+
VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio -- %d ",\
regenerateAudio);
+
if (regenerateAudio) {
M4OSA_TRACE1_0("Calling Generate Audio now");
result = videoEditor_generateAudio(pEnv,
pContext,
(M4OSA_Char*)pContext->mAudioSettings->pFile,
(M4OSA_Char*)pContext->mAudioSettings->pPCMFilePath);
+
+ videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
+ (M4NO_ERROR != result), result);
+ if (needToBeLoaded == false) {
+ goto videoEditor_populateSettings_cleanup;
+ }
+
regenerateAudio = false;
pEnv->SetBooleanField(thiz,fid,regenerateAudio);
}
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio()");
/* Audio mix and duck */
fid = pEnv->GetFieldID(audioSettingClazz,"ducking_threshold","I");
pContext->mAudioSettings->uiInDucking_threshold
= pEnv->GetIntField(audioSettingObject,fid);
+
M4OSA_TRACE1_1("ducking threshold = %d",
pContext->mAudioSettings->uiInDucking_threshold);
fid = pEnv->GetFieldID(audioSettingClazz,"ducking_lowVolume","I");
pContext->mAudioSettings->uiInDucking_lowVolume
= pEnv->GetIntField(audioSettingObject,fid);
+
M4OSA_TRACE1_1("ducking lowVolume = %d",
pContext->mAudioSettings->uiInDucking_lowVolume);
@@ -1714,6 +1857,7 @@
= pEnv->GetBooleanField(audioSettingObject,fid);
M4OSA_TRACE1_1("ducking lowVolume = %d",
pContext->mAudioSettings->bInDucking_enable);
+
} else {
if (pContext->mAudioSettings != M4OSA_NULL) {
pContext->mAudioSettings->pFile = M4OSA_NULL;
@@ -1734,22 +1878,27 @@
fid = pEnv->GetFieldID(engineClass,"mRegenerateAudio","Z");
bool regenerateAudio = pEnv->GetBooleanField(thiz,fid);
- if(!regenerateAudio) {
+ if (!regenerateAudio) {
regenerateAudio = true;
pEnv->SetBooleanField(thiz,fid,regenerateAudio);
}
}
}
- if (pContext->pEditSettings != NULL )
+
+ if (pContext->pEditSettings != NULL)
{
result = pContext->mPreviewController->loadEditSettings(pContext->pEditSettings,
- pContext->mAudioSettings);
+ pContext->mAudioSettings);
videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
(M4NO_ERROR != result), result);
- pContext->mPreviewController->setJniCallback((void*)pContext,
- (jni_progress_callback_fct)jniPreviewProgressCallback);
+ if (needToBeLoaded) {
+ pContext->mPreviewController->setJniCallback((void*)pContext,
+ (jni_progress_callback_fct)jniPreviewProgressCallback);
+ }
+ }
+videoEditor_populateSettings_cleanup:
j = 0;
while (j < nbOverlays)
{
@@ -1760,14 +1909,22 @@
pContext->pEditSettings->\
Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data = M4OSA_NULL;
}
- if (pContext->pEditSettings->Effects[pOverlayIndex[j]].xVSS.pFramingBuffer != M4OSA_NULL) {
- M4OSA_free((M4OSA_MemAddr32)pContext->pEditSettings->\
- Effects[pOverlayIndex[j]].xVSS.pFramingBuffer);
- pContext->pEditSettings->Effects[pOverlayIndex[j]].xVSS.pFramingBuffer = M4OSA_NULL;
- }
j++;
}
- }
+
+ j = 0;
+ while (j < pContext->pEditSettings->nbEffects)
+ {
+ if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) {
+ if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer != M4OSA_NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pContext->pEditSettings->\
+ Effects[j].xVSS.pFramingBuffer);
+ pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer = M4OSA_NULL;
+ }
+ }
+ j++;
+ }
+
if (pOverlayIndex != M4OSA_NULL)
{
M4OSA_free((M4OSA_MemAddr32)pOverlayIndex);
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 27c8aea..2df6d68 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -116,4 +116,9 @@
<!-- Default for Settings.System.USER_ROTATION -->
<integer name="def_user_rotation">0</integer>
+
+ <!-- Default for Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE. <=0 if no limit -->
+ <integer name="def_download_manager_max_bytes_over_mobile">-1</integer>
+ <!-- Default for Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE. <=0 if no limit -->
+ <integer name="def_download_manager_recommended_max_bytes_over_mobile">-1</integer>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 580113c..49b71e2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1295,6 +1295,20 @@
loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
R.string.def_accessibility_web_content_key_bindings);
+
+ final int maxBytes = mContext.getResources().getInteger(
+ R.integer.def_download_manager_max_bytes_over_mobile);
+ if (maxBytes > 0) {
+ loadSetting(stmt, Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE,
+ Integer.toString(maxBytes));
+ }
+
+ final int recommendedMaxBytes = mContext.getResources().getInteger(
+ R.integer.def_download_manager_recommended_max_bytes_over_mobile);
+ if (recommendedMaxBytes > 0) {
+ loadSetting(stmt, Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
+ Integer.toString(recommendedMaxBytes));
+ }
} finally {
if (stmt != null) stmt.close();
}
diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java
index 90318f1..ef00b08f 100644
--- a/services/java/com/android/server/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/ScreenRotationAnimation.java
@@ -39,10 +39,48 @@
static final String TAG = "ScreenRotationAnimation";
static final boolean DEBUG = false;
+ static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
+
+ class BlackSurface {
+ final int left;
+ final int top;
+ final Surface surface;
+
+ BlackSurface(SurfaceSession session, int layer, int l, int t, int w, int h)
+ throws Surface.OutOfResourcesException {
+ left = l;
+ top = t;
+ surface = new Surface(session, 0, "BlackSurface",
+ -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
+ surface.setAlpha(1.0f);
+ surface.setLayer(FREEZE_LAYER);
+ }
+
+ void setMatrix(Matrix matrix) {
+ mTmpMatrix.setTranslate(left, top);
+ mTmpMatrix.postConcat(matrix);
+ mTmpMatrix.getValues(mTmpFloats);
+ surface.setPosition((int)mTmpFloats[Matrix.MTRANS_X],
+ (int)mTmpFloats[Matrix.MTRANS_Y]);
+ surface.setMatrix(
+ mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
+ mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
+ if (false) {
+ Slog.i(TAG, "Black Surface @ (" + left + "," + top + "): ("
+ + mTmpFloats[Matrix.MTRANS_X] + ","
+ + mTmpFloats[Matrix.MTRANS_Y] + ") matrix=["
+ + mTmpFloats[Matrix.MSCALE_X] + ","
+ + mTmpFloats[Matrix.MSCALE_Y] + "]["
+ + mTmpFloats[Matrix.MSKEW_X] + ","
+ + mTmpFloats[Matrix.MSKEW_Y] + "]");
+ }
+ }
+ }
+
final Context mContext;
final Display mDisplay;
Surface mSurface;
- Surface mBlackSurface;
+ BlackSurface[] mBlackSurfaces;
int mWidth, mHeight;
int mSnapshotRotation;
@@ -60,6 +98,7 @@
final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
final Matrix mSnapshotInitialMatrix = new Matrix();
final Matrix mSnapshotFinalMatrix = new Matrix();
+ final Matrix mTmpMatrix = new Matrix();
final float[] mTmpFloats = new float[9];
public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
@@ -97,23 +136,11 @@
try {
mSurface = new Surface(session, 0, "FreezeSurface",
-1, mWidth, mHeight, PixelFormat.OPAQUE, 0);
- mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 200);
+ mSurface.setLayer(FREEZE_LAYER + 1);
} catch (Surface.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate freeze surface", e);
}
- if (true) {
- try {
- int size = mOriginalWidth > mOriginalHeight ? mOriginalWidth : mOriginalHeight;
- mBlackSurface = new Surface(session, 0, "BlackSurface",
- -1, size, size, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
- mBlackSurface.setAlpha(1.0f);
- mBlackSurface.setLayer(0);
- } catch (Surface.OutOfResourcesException e) {
- Slog.w(TAG, "Unable to allocate black surface", e);
- }
- }
-
setRotation(display.getRotation());
if (mSurface != null) {
@@ -138,7 +165,7 @@
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
c.drawBitmap(screenshot, 0, 0, paint);
} else {
- c.drawColor(Color.GREEN, PorterDuff.Mode.SRC);
+ c.drawColor(Color.BLACK, PorterDuff.Mode.SRC);
}
mSurface.unlockCanvasAndPost(c);
@@ -221,7 +248,8 @@
/**
* Returns true if animating.
*/
- public boolean dismiss(long maxAnimationDuration, float animationScale) {
+ public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
+ float animationScale) {
// Figure out how the screen has moved from the original rotation.
int delta = deltaRotation(mCurRotation, mOriginalRotation);
if (false && delta == 0) {
@@ -277,6 +305,26 @@
mEnterAnimation.restrictDuration(maxAnimationDuration);
mEnterAnimation.scaleCurrentDuration(animationScale);
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
+ ">>> OPEN TRANSACTION ScreenRotationAnimation.dismiss");
+ Surface.openTransaction();
+
+ mBlackSurfaces = new BlackSurface[4];
+ try {
+ final int w = mDisplayMetrics.widthPixels;
+ final int h = mDisplayMetrics.heightPixels;
+ mBlackSurfaces[0] = new BlackSurface(session, FREEZE_LAYER, -w, -h, w, h*2);
+ mBlackSurfaces[1] = new BlackSurface(session, FREEZE_LAYER, 0, -h, w*2, h);
+ mBlackSurfaces[2] = new BlackSurface(session, FREEZE_LAYER, w, 0, w, h*2);
+ mBlackSurfaces[3] = new BlackSurface(session, FREEZE_LAYER, -w, h, w*2, h);
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.w(TAG, "Unable to allocate black surface", e);
+ } finally {
+ Surface.closeTransaction();
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
+ "<<< CLOSE TRANSACTION ScreenRotationAnimation.dismiss");
+ }
+
return true;
}
@@ -285,9 +333,13 @@
mSurface.destroy();
mSurface = null;
}
- if (mBlackSurface != null) {
- mBlackSurface.destroy();
- mBlackSurface = null;
+ if (mBlackSurfaces != null) {
+ for (int i=0; i<mBlackSurfaces.length; i++) {
+ if (mBlackSurfaces[i] != null) {
+ mBlackSurfaces[i].surface.destroy();
+ }
+ }
+ mBlackSurfaces = null;
}
if (mExitAnimation != null) {
mExitAnimation.cancel();
@@ -325,12 +377,7 @@
mExitAnimation = null;
mExitTransformation.clear();
if (mSurface != null) {
- mSurface.destroy();
- mSurface = null;
- }
- if (mBlackSurface != null) {
- mBlackSurface.destroy();
- mBlackSurface = null;
+ mSurface.hide();
}
}
}
@@ -343,6 +390,21 @@
mEnterAnimation.cancel();
mEnterAnimation = null;
mEnterTransformation.clear();
+ if (mBlackSurfaces != null) {
+ for (int i=0; i<mBlackSurfaces.length; i++) {
+ if (mBlackSurfaces[i] != null) {
+ mBlackSurfaces[i].surface.hide();
+ }
+ }
+ }
+ } else {
+ if (mBlackSurfaces != null) {
+ for (int i=0; i<mBlackSurfaces.length; i++) {
+ if (mBlackSurfaces[i] != null) {
+ mBlackSurfaces[i].setMatrix(mEnterTransformation.getMatrix());
+ }
+ }
+ }
}
}
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 7a3ef14..a98c3e3 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5101,6 +5101,9 @@
}
Binder.restoreCallingIdentity(ident);
+ // Constrain frame to the screen size.
+ frame.intersect(0, 0, dw, dh);
+
if (frame.isEmpty() || maxLayer == 0) {
return null;
}
@@ -7839,7 +7842,7 @@
if (selfTransformation) {
tmpMatrix.postConcat(mTransformation.getMatrix());
}
- tmpMatrix.postTranslate(frame.left, frame.top);
+ tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset);
if (attachedTransformation != null) {
tmpMatrix.postConcat(attachedTransformation.getMatrix());
}
@@ -7863,8 +7866,8 @@
mDtDx = tmpFloats[Matrix.MSKEW_Y];
mDsDy = tmpFloats[Matrix.MSKEW_X];
mDtDy = tmpFloats[Matrix.MSCALE_Y];
- int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
- int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
+ int x = (int)tmpFloats[Matrix.MTRANS_X];
+ int y = (int)tmpFloats[Matrix.MTRANS_Y];
int w = frame.width();
int h = frame.height();
mShownFrame.set(x, y, x+w, y+h);
@@ -9780,6 +9783,7 @@
boolean animating = false;
boolean createWatermark = false;
boolean updateRotation = false;
+ boolean screenRotationFinished = false;
if (mFxSession == null) {
mFxSession = new SurfaceSession();
@@ -9876,7 +9880,7 @@
if (mScreenRotationAnimation.stepAnimation(currentTime)) {
animating = true;
} else {
- mScreenRotationAnimation = null;
+ screenRotationFinished = true;
updateRotation = true;
}
}
@@ -11040,6 +11044,11 @@
mTurnOnScreen = false;
}
+ if (screenRotationFinished && mScreenRotationAnimation != null) {
+ mScreenRotationAnimation.kill();
+ mScreenRotationAnimation = null;
+ }
+
if (updateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
boolean changed = setRotationUncheckedLocked(
@@ -11379,7 +11388,7 @@
if (CUSTOM_SCREEN_ROTATION) {
if (mScreenRotationAnimation != null) {
- if (mScreenRotationAnimation.dismiss(MAX_ANIMATION_DURATION,
+ if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
mTransitionAnimationScale)) {
requestAnimationLocked(0);
} else {
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index 11f8feb..f79166d 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -30,29 +30,12 @@
namespace android {
// ---------------------------------------------------------------------------
-bool LayerDim::sUseTexture;
-GLuint LayerDim::sTexId;
-EGLImageKHR LayerDim::sImage;
-int32_t LayerDim::sWidth;
-int32_t LayerDim::sHeight;
-
-// ---------------------------------------------------------------------------
-
LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client)
: LayerBaseClient(flinger, display, client)
{
}
-void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
-{
- sTexId = -1;
- sImage = EGL_NO_IMAGE_KHR;
- sWidth = w;
- sHeight = h;
- sUseTexture = false;
-}
-
LayerDim::~LayerDim()
{
}
@@ -84,15 +67,7 @@
#endif
glDisable(GL_TEXTURE_2D);
- GLshort w = sWidth;
- GLshort h = sHeight;
- const GLshort vertices[4][2] = {
- { 0, 0 },
- { 0, h },
- { w, h },
- { w, 0 }
- };
- glVertexPointer(2, GL_SHORT, 0, vertices);
+ glVertexPointer(2, GL_FLOAT, 0, mVertices);
while (it != end) {
const Rect& r = *it++;
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index f032314..5631c0a 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -31,11 +31,6 @@
class LayerDim : public LayerBaseClient
{
- static bool sUseTexture;
- static GLuint sTexId;
- static EGLImageKHR sImage;
- static int32_t sWidth;
- static int32_t sHeight;
public:
LayerDim(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client);
@@ -45,8 +40,6 @@
virtual bool needsBlending() const { return true; }
virtual bool isSecure() const { return false; }
virtual const char* getTypeId() const { return "LayerDim"; }
-
- static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h);
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 87b66ea..fd3f0c2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -259,8 +259,6 @@
glLoadIdentity();
glOrthof(0, w, h, 0, 0, 1);
- LayerDim::initDimmer(this, w, h);
-
mReadyToRunBarrier.open();
/*
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index 2edfc23..5eaa5a0 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -61,9 +61,9 @@
* @hide
*/
public static CellLocation newFromBundle(Bundle bundle) {
- // TelephonyManager.getDefault().getPhoneType() handles the case when
+ // TelephonyManager.getDefault().getCurrentPhoneType() handles the case when
// ITelephony interface is not up yet.
- switch(TelephonyManager.getDefault().getPhoneType()) {
+ switch(TelephonyManager.getDefault().getCurrentPhoneType()) {
case Phone.PHONE_TYPE_CDMA:
return new CdmaCellLocation(bundle);
case Phone.PHONE_TYPE_GSM:
@@ -89,9 +89,9 @@
*
*/
public static CellLocation getEmpty() {
- // TelephonyManager.getDefault().getPhoneType() handles the case when
+ // TelephonyManager.getDefault().getCurrentPhoneType() handles the case when
// ITelephony interface is not up yet.
- switch(TelephonyManager.getDefault().getPhoneType()) {
+ switch(TelephonyManager.getDefault().getCurrentPhoneType()) {
case Phone.PHONE_TYPE_CDMA:
return new CdmaCellLocation();
case Phone.PHONE_TYPE_GSM:
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 0746562..93d89a7 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -124,7 +124,7 @@
*/
public static SmsMessage createFromPdu(byte[] pdu) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
@@ -146,7 +146,7 @@
*/
public static SmsMessage newFromCMT(String[] lines){
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMT(lines);
@@ -160,7 +160,7 @@
/** @hide */
protected static SmsMessage newFromCMTI(String line) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMTI(line);
@@ -174,7 +174,7 @@
/** @hide */
public static SmsMessage newFromCDS(String line) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCDS(line);
@@ -188,7 +188,7 @@
/** @hide */
public static SmsMessage newFromParcel(Parcel p) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromParcel(p);
@@ -211,7 +211,7 @@
*/
public static SmsMessage createFromEfRecord(int index, byte[] data) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
@@ -229,7 +229,7 @@
* length in bytes (not hex chars) less the SMSC header
*/
public static int getTPLayerLengthForPDU(String pdu) {
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
return com.android.internal.telephony.cdma.SmsMessage.getTPLayerLengthForPDU(pdu);
@@ -265,7 +265,7 @@
* class).
*/
public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
TextEncodingDetails ted = (PHONE_TYPE_CDMA == activePhone) ?
com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly) :
com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
@@ -288,7 +288,7 @@
* @hide
*/
public static ArrayList<String> fragmentText(String text) {
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
TextEncodingDetails ted = (PHONE_TYPE_CDMA == activePhone) ?
com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false) :
com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false);
@@ -385,7 +385,7 @@
String destinationAddress, String message,
boolean statusReportRequested, byte[] header) {
SubmitPduBase spb;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
@@ -410,7 +410,7 @@
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, String message, boolean statusReportRequested) {
SubmitPduBase spb;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
@@ -439,7 +439,7 @@
String destinationAddress, short destinationPort, byte[] data,
boolean statusReportRequested) {
SubmitPduBase spb;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
@@ -708,7 +708,7 @@
* @hide
*/
private static final SmsMessageBase getSmsFacility(){
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
return new com.android.internal.telephony.cdma.SmsMessage();
} else {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 88d9436..821e39f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.util.Log;
import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.ITelephony;
@@ -55,14 +56,21 @@
public class TelephonyManager {
private static final String TAG = "TelephonyManager";
- private Context mContext;
- private ITelephonyRegistry mRegistry;
+ private static Context sContext;
+ private static ITelephonyRegistry sRegistry;
/** @hide */
public TelephonyManager(Context context) {
- mContext = context;
- mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
+ if (sContext == null) {
+ sContext = context;
+
+ sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
+ } else {
+ Log.e(TAG, "Hidden constructor called more than once per process!");
+ Log.e(TAG, "Original: " + sContext.getPackageName() + ", new: " +
+ context.getPackageName());
+ }
}
/** @hide */
@@ -71,7 +79,8 @@
private static TelephonyManager sInstance = new TelephonyManager();
- /** @hide */
+ /** @hide
+ /* @deprecated - use getSystemService as described above */
public static TelephonyManager getDefault() {
return sInstance;
}
@@ -276,15 +285,17 @@
public static final int PHONE_TYPE_SIP = Phone.PHONE_TYPE_SIP;
/**
- * Returns a constant indicating the device phone type. This
- * indicates the type of radio used to transmit voice calls.
+ * Returns the current phone type.
+ * TODO: This is a last minute change and hence hidden.
*
* @see #PHONE_TYPE_NONE
* @see #PHONE_TYPE_GSM
* @see #PHONE_TYPE_CDMA
* @see #PHONE_TYPE_SIP
+ *
+ * {@hide}
*/
- public int getPhoneType() {
+ public int getCurrentPhoneType() {
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
@@ -304,6 +315,21 @@
}
}
+ /**
+ * Returns a constant indicating the device phone type. This
+ * indicates the type of radio used to transmit voice calls.
+ *
+ * @see #PHONE_TYPE_NONE
+ * @see #PHONE_TYPE_GSM
+ * @see #PHONE_TYPE_CDMA
+ * @see #PHONE_TYPE_SIP
+ */
+ public int getPhoneType() {
+ if (!isVoiceCapable()) {
+ return PHONE_TYPE_NONE;
+ }
+ return getCurrentPhoneType();
+ }
private int getPhoneTypeFromProperty() {
int type =
@@ -872,10 +898,10 @@
* LISTEN_ flags.
*/
public void listen(PhoneStateListener listener, int events) {
- String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
+ String pkgForDebug = sContext != null ? sContext.getPackageName() : "<unknown>";
try {
Boolean notifyNow = (getITelephony() != null);
- mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
+ sRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
} catch (RemoteException ex) {
// system process dead
} catch (NullPointerException ex) {
@@ -950,7 +976,8 @@
* @hide pending API review
*/
public boolean isVoiceCapable() {
- return mContext.getResources().getBoolean(
+ if (sContext == null) return true;
+ return sContext.getResources().getBoolean(
com.android.internal.R.bool.config_voice_capable);
}
@@ -966,7 +993,8 @@
* @hide pending API review
*/
public boolean isSmsCapable() {
- return mContext.getResources().getBoolean(
+ if (sContext == null) return true;
+ return sContext.getResources().getBoolean(
com.android.internal.R.bool.config_sms_capable);
}
}
diff --git a/telephony/java/android/telephony/gsm/SmsMessage.java b/telephony/java/android/telephony/gsm/SmsMessage.java
index 0c63c37..6880175 100644
--- a/telephony/java/android/telephony/gsm/SmsMessage.java
+++ b/telephony/java/android/telephony/gsm/SmsMessage.java
@@ -154,7 +154,7 @@
@Deprecated
public static SmsMessage createFromPdu(byte[] pdu) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
@@ -177,7 +177,7 @@
@Deprecated
public static SmsMessage newFromCMT(String[] lines){
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMT(lines);
@@ -193,7 +193,7 @@
@Deprecated
protected static SmsMessage newFromCMTI(String line) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMTI(line);
@@ -209,7 +209,7 @@
@Deprecated
public static SmsMessage newFromCDS(String line) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCDS(line);
@@ -225,7 +225,7 @@
@Deprecated
public static SmsMessage newFromParcel(Parcel p) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromParcel(p);
@@ -250,7 +250,7 @@
@Deprecated
public static SmsMessage createFromEfRecord(int index, byte[] data) {
SmsMessageBase wrappedMessage;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
@@ -270,7 +270,7 @@
*/
@Deprecated
public static int getTPLayerLengthForPDU(String pdu) {
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
return com.android.internal.telephony.cdma.SmsMessage.getTPLayerLengthForPDU(pdu);
@@ -367,7 +367,7 @@
String destinationAddress, String message,
boolean statusReportRequested, byte[] header) {
SubmitPduBase spb;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
@@ -394,7 +394,7 @@
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, String message, boolean statusReportRequested) {
SubmitPduBase spb;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
@@ -425,7 +425,7 @@
String destinationAddress, short destinationPort, byte[] data,
boolean statusReportRequested) {
SubmitPduBase spb;
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
@@ -739,7 +739,7 @@
* @deprecated Use android.telephony.SmsMessage.
*/
private static final SmsMessageBase getSmsFacility(){
- int activePhone = TelephonyManager.getDefault().getPhoneType();
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
if (PHONE_TYPE_CDMA == activePhone) {
return new com.android.internal.telephony.cdma.SmsMessage();
} else {
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 2895b69..fc50334 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -78,6 +78,24 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity
+ android:name="ViewLayersActivity4"
+ android:label="_ViewLayers4">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="ViewLayersActivity5"
+ android:label="_ViewLayers5">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
<activity
android:name="AlphaLayersActivity"
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_4.xml b/tests/HwAccelerationTest/res/layout/view_layers_4.xml
new file mode 100644
index 0000000..5436737
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/view_layers_4.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1">
+
+ <Button
+ android:onClick="setListTranslucent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Set translucent" />
+
+ <Button
+ android:onClick="setListOpaque"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Set opaque" />
+
+ </LinearLayout>
+
+ <ListView
+ android:id="@+id/list1"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+
+</LinearLayout>
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_5.xml b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
new file mode 100644
index 0000000..653f3a8
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1">
+
+ <Button
+ android:onClick="setLayerEnabled"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Enable layer" />
+
+ <Button
+ android:onClick="setLayerDisabled"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Disable layer" />
+
+ </LinearLayout>
+
+ <ListView
+ android:id="@+id/list1"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+
+</LinearLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
new file mode 100644
index 0000000..6072c6e
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ViewLayersActivity4 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.view_layers_4);
+
+ setupList(R.id.list1);
+ }
+
+ public void setListTranslucent(View v) {
+ findViewById(R.id.list1).setAlpha(0.5f);
+ }
+
+ public void setListOpaque(View v) {
+ findViewById(R.id.list1).setAlpha(1.0f);
+ }
+
+ private void setupList(int listId) {
+ final ListView list = (ListView) findViewById(listId);
+ list.setAdapter(new SimpleListAdapter(this));
+ list.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }
+
+ private static class SimpleListAdapter extends ArrayAdapter<String> {
+ public SimpleListAdapter(Context context) {
+ super(context, android.R.layout.simple_list_item_1, DATA_LIST);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView v = (TextView) super.getView(position, convertView, parent);
+ final Resources r = getContext().getResources();
+ final DisplayMetrics metrics = r.getDisplayMetrics();
+ v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
+ v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
+ null, null, null);
+ return v;
+ }
+ }
+
+ private static final String[] DATA_LIST = {
+ "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
+ "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
+ "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
+ "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
+ "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
+ "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
+ "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
+ "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
+ "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+ "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+ "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+ "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
+ "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
+ "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
+ "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
+ "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
+ "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
+ "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
+ "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
+ "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
+ "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
+ "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
+ "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
+ "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
+ "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
+ "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
+ "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
+ "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
+ "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
+ "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
+ "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
+ "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
+ "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
+ "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
+ "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
+ "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
+ "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
+ "Ukraine", "United Arab Emirates", "United Kingdom",
+ "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
+ "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
+ "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
+ };
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
new file mode 100644
index 0000000..95a5b0d
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ViewLayersActivity5 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.view_layers_5);
+
+ setupList(R.id.list1);
+ }
+
+ public void setLayerDisabled(View v) {
+ ((ViewGroup) findViewById(R.id.list1).getParent()).setChildrenLayersEnabled(false);
+ }
+
+ public void setLayerEnabled(View v) {
+ ((ViewGroup) findViewById(R.id.list1).getParent()).setChildrenLayersEnabled(true);
+ }
+
+ private void setupList(int listId) {
+ final Paint p = new Paint();
+ p.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
+
+ final ListView list = (ListView) findViewById(listId);
+ list.setAdapter(new SimpleListAdapter(this));
+ list.setLayerType(View.LAYER_TYPE_HARDWARE, p);
+ }
+
+ private static class SimpleListAdapter extends ArrayAdapter<String> {
+ public SimpleListAdapter(Context context) {
+ super(context, android.R.layout.simple_list_item_1, DATA_LIST);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView v = (TextView) super.getView(position, convertView, parent);
+ final Resources r = getContext().getResources();
+ final DisplayMetrics metrics = r.getDisplayMetrics();
+ v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
+ v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
+ null, null, null);
+ return v;
+ }
+ }
+
+ private static final String[] DATA_LIST = {
+ "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
+ "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
+ "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
+ "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
+ "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
+ "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
+ "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
+ "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
+ "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+ "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+ "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+ "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
+ "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
+ "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
+ "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
+ "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
+ "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
+ "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
+ "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
+ "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
+ "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
+ "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
+ "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
+ "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
+ "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
+ "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
+ "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
+ "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
+ "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
+ "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
+ "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
+ "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
+ "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
+ "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
+ "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
+ "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
+ "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
+ "Ukraine", "United Arab Emirates", "United Kingdom",
+ "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
+ "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
+ "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
+ };
+}
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
new file mode 100644
index 0000000..03f3980
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import com.android.layoutlib.bridge.impl.RenderSessionImpl;
+
+import android.content.res.Resources.NotFoundException;
+import android.content.res.Resources.Theme;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link Theme}
+ *
+ * Through the layoutlib_create tool, the original methods of Theme have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class Resources_Theme_Delegate {
+
+ /*package*/ static TypedArray obtainStyledAttributes(
+ Resources thisResources, Theme thisTheme,
+ int[] attrs) {
+ return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+ }
+
+ /*package*/ static TypedArray obtainStyledAttributes(
+ Resources thisResources, Theme thisTheme,
+ int resid, int[] attrs)
+ throws NotFoundException {
+ return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs);
+ }
+
+ /*package*/ static TypedArray obtainStyledAttributes(
+ Resources thisResources, Theme thisTheme,
+ AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
+ return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(
+ set, attrs, defStyleAttr, defStyleRes);
+ }
+
+ /*package*/ static boolean resolveAttribute(
+ Resources thisResources, Theme thisTheme,
+ int resid, TypedValue outValue,
+ boolean resolveRefs) {
+ return RenderSessionImpl.getCurrentContext().resolveThemeAttribute(
+ resid, outValue, resolveRefs);
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 037ad23..4220ddd 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -56,6 +56,7 @@
import android.os.Looper;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@@ -77,7 +78,6 @@
public final class BridgeContext extends Activity {
private Resources mSystemResources;
- private Theme mTheme;
private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
private final Object mProjectKey;
private final DisplayMetrics mMetrics;
@@ -87,7 +87,7 @@
private final Map<Object, Map<String, String>> mDefaultPropMaps =
new IdentityHashMap<Object, Map<String,String>>();
- // maps for dynamically generated id representing style objects (IStyleResourceValue)
+ // maps for dynamically generated id representing style objects (StyleResourceValue)
private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap;
private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style
@@ -222,6 +222,50 @@
return mParserStack.get(mParserStack.size() - 2);
}
+ public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
+ Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid);
+ if (resourceInfo == null) {
+ resourceInfo = mProjectCallback.resolveResourceId(resid);
+ }
+
+ if (resourceInfo == null) {
+ return false;
+ }
+
+ ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond());
+ if (resolveRefs) {
+ value = mRenderResources.resolveResValue(value);
+ }
+
+ // check if this is a style resource
+ if (value instanceof StyleResourceValue) {
+ // get the id that will represent this style.
+ outValue.resourceId = getDynamicIdByStyle((StyleResourceValue)value);
+ return true;
+ }
+
+
+ int a;
+ // if this is a framework value.
+ if (value.isFramework()) {
+ // look for idName in the android R classes.
+ // use 0 a default res value as it's not a valid id value.
+ a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/);
+ } else {
+ // look for idName in the project R class.
+ // use 0 a default res value as it's not a valid id value.
+ a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/);
+ }
+
+ if (a != 0) {
+ outValue.resourceId = a;
+ return true;
+ }
+
+ return false;
+ }
+
+
// ------------- Activity Methods
@Override
@@ -275,7 +319,7 @@
@Override
public final TypedArray obtainStyledAttributes(int resid, int[] attrs)
throws Resources.NotFoundException {
- // get the IStyleResourceValue based on the resId;
+ // get the StyleResourceValue based on the resId;
StyleResourceValue style = getStyleByDynamicId(resid);
if (style == null) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index d816d18..fa04697 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -334,7 +334,10 @@
Bridge.setLog(null);
mContext.getRenderResources().setFrameworkResourceIdProvider(null);
mContext.getRenderResources().setLogger(null);
+ }
+ public static BridgeContext getCurrentContext() {
+ return sCurrentContext;
}
/**
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
new file mode 100644
index 0000000..ab01a394
--- /dev/null
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.icu;
+
+import java.util.Locale;
+
+/**
+ * Delegate implementing the native methods of libcore.icu.ICU
+ *
+ * Through the layoutlib_create tool, the original native methods of ICU have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class ICU_Delegate {
+
+ /*package*/ static String toLowerCase(String s, String localeName) {
+ return s.toLowerCase();
+ }
+
+ /*package*/ static String toUpperCase(String s, String localeName) {
+ return s.toUpperCase();
+ }
+
+ // --- Native methods accessing ICU's database.
+
+ /*package*/ static String[] getAvailableBreakIteratorLocalesNative() {
+ return new String[0];
+ }
+
+ /*package*/ static String[] getAvailableCalendarLocalesNative() {
+ return new String[0];
+ }
+
+ /*package*/ static String[] getAvailableCollatorLocalesNative() {
+ return new String[0];
+ }
+
+ /*package*/ static String[] getAvailableDateFormatLocalesNative() {
+ return new String[0];
+ }
+
+ /*package*/ static String[] getAvailableLocalesNative() {
+ return new String[0];
+ }
+
+ /*package*/ static String[] getAvailableNumberFormatLocalesNative() {
+ return new String[0];
+ }
+
+ /*package*/ static String getCurrencyCodeNative(String locale) {
+ return "";
+ }
+
+ /*package*/ static int getCurrencyFractionDigitsNative(String currencyCode) {
+ return 0;
+ }
+
+ /*package*/ static String getCurrencySymbolNative(String locale, String currencyCode) {
+ return "";
+ }
+
+ /*package*/ static String getDisplayCountryNative(String countryCode, String locale) {
+ return "";
+ }
+
+ /*package*/ static String getDisplayLanguageNative(String languageCode, String locale) {
+ return "";
+ }
+
+ /*package*/ static String getDisplayVariantNative(String variantCode, String locale) {
+ return "";
+ }
+
+ /*package*/ static String getISO3CountryNative(String locale) {
+ return "";
+ }
+
+ /*package*/ static String getISO3LanguageNative(String locale) {
+ return "";
+ }
+
+ /*package*/ static String[] getISOLanguagesNative() {
+ return Locale.getISOLanguages();
+ }
+
+ /*package*/ static String[] getISOCountriesNative() {
+ return Locale.getISOCountries();
+ }
+
+ /*package*/ static boolean initLocaleDataImpl(String locale, LocaleData result) {
+
+ // Used by Calendar.
+ result.firstDayOfWeek = Integer.valueOf(1);
+ result.minimalDaysInFirstWeek = Integer.valueOf(1);
+
+ // Used by DateFormatSymbols.
+ result.amPm = new String[] { "AM", "PM" };
+ result.eras = new String[] { "BC", "AD" };
+
+ result.longMonthNames = new String[] { "January", "February", "March", "April", "May",
+ "June", "July", "August", "September", "October", "November", "December" };
+ result.shortMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May",
+ "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ result.longStandAloneMonthNames = result.longMonthNames;
+ result.shortStandAloneMonthNames = result.shortMonthNames;
+
+ result.longWeekdayNames = new String[] {
+ "Monday" ,"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
+ result.shortWeekdayNames = new String[] {
+ "Mon" ,"Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+ result.longStandAloneWeekdayNames = result.longWeekdayNames;
+ result.shortStandAloneWeekdayNames = result.shortWeekdayNames;
+
+ result.fullTimeFormat = "";
+ result.longTimeFormat = "";
+ result.mediumTimeFormat = "";
+ result.shortTimeFormat = "";
+
+ result.fullDateFormat = "";
+ result.longDateFormat = "";
+ result.mediumDateFormat = "";
+ result.shortDateFormat = "";
+
+ // Used by DecimalFormatSymbols.
+ result.zeroDigit = '0';
+ result.digit = '0';
+ result.decimalSeparator = '.';
+ result.groupingSeparator = ',';
+ result.patternSeparator = ' ';
+ result.percent = '%';
+ result.perMill = '\u2030';
+ result.monetarySeparator = ' ';
+ result.minusSign = '-';
+ result.exponentSeparator = "e";
+ result.infinity = "\u221E";
+ result.NaN = "NaN";
+ // Also used by Currency.
+ result.currencySymbol = "$";
+ result.internationalCurrencySymbol = "USD";
+
+ // Used by DecimalFormat and NumberFormat.
+ result.numberPattern = "%f";
+ result.integerPattern = "%d";
+ result.currencyPattern = "%s";
+ result.percentPattern = "%f";
+
+ return true;
+ }
+}
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestDelegates.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestDelegates.java
index 0ff1925..a4140e3 100644
--- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestDelegates.java
+++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestDelegates.java
@@ -56,8 +56,9 @@
// extract the class name
String className = methodName.substring(0, methodName.indexOf('#'));
+ String targetClassName = className.replace('$', '_') + "_Delegate";
- loadAndCompareClasses(className, className + "_Delegate");
+ loadAndCompareClasses(className, targetClassName);
}
}
@@ -98,6 +99,16 @@
parameters = newParameters;
}
+ // if the original class is an inner class that's not static, then
+ // we add this on the enclosing class at the beginning
+ if (originalClass.getEnclosingClass() != null &&
+ (originalClass.getModifiers() & Modifier.STATIC) == 0) {
+ Class<?>[] newParameters = new Class<?>[parameters.length + 1];
+ newParameters[0] = originalClass.getEnclosingClass();
+ System.arraycopy(parameters, 0, newParameters, 1, parameters.length);
+ parameters = newParameters;
+ }
+
try {
// try to load the method with the given parameter types.
Method delegateMethod = delegateClass.getDeclaredMethod(originalMethod.getName(),
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 55e9e48..291f076d 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -95,13 +95,14 @@
*/
private final static String[] DELEGATE_METHODS = new String[] {
"android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
+ "android.content.res.Resources$Theme#obtainStyledAttributes",
+ "android.content.res.Resources$Theme#resolveAttribute",
"android.os.Handler#sendMessageAtTime",
"android.os.Build#getString",
"android.view.LayoutInflater#rInflate",
"android.view.View#isInEditMode",
"com.android.internal.util.XmlUtils#convertValueToInt",
// TODO: comment out once DelegateClass is working
- // "android.content.res.Resources$Theme#obtainStyledAttributes",
};
/**
@@ -147,6 +148,7 @@
"android.graphics.Xfermode",
"android.os.SystemClock",
"android.util.FloatMath",
+ "libcore.icu.ICU",
};
/**
@@ -154,8 +156,6 @@
* "package.package.OuterClass$InnerClass#MethodName".
*/
private final static String[] OVERRIDDEN_METHODS = new String[] {
- // TODO: remove once DelegateClass is working
- "android.content.res.Resources$Theme#obtainStyledAttributes",
};
/**