Merge change 25128 into eclair
* changes:
Support CbYCrY -> RGB565 color conversion in IOMXRenderer.
diff --git a/api/current.xml b/api/current.xml
index 38490f3..7562f2e 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6825,7 +6825,7 @@
value="16843221"
static="true"
final="true"
- deprecated="deprecated"
+ deprecated="not deprecated"
visibility="public"
>
</field>
@@ -150079,6 +150079,19 @@
visibility="public"
>
</method>
+<method name="setOnTop"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onTop" type="boolean">
+</parameter>
+</method>
</class>
<class name="TouchDelegate"
extends="java.lang.Object"
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 39ed769..5b55252 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -11,6 +11,7 @@
libstagefright
LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
frameworks/base/media/libstagefright \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
@@ -32,6 +33,7 @@
libstagefright
LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
frameworks/base/media/libstagefright \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 6abed93..c13893a 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1445,13 +1445,18 @@
intent.getComponent().getClassName())) {
createNoCredentialsPermissionNotification(account, intent);
} else {
+ final Integer notificationId = getSigninRequiredNotificationId(account);
+ intent.addCategory(String.valueOf(notificationId));
Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
0 /* when */);
- n.setLatestEventInfo(mContext, mContext.getText(R.string.notification_title),
+ final String notificationTitleFormat =
+ mContext.getText(R.string.notification_title).toString();
+ n.setLatestEventInfo(mContext,
+ String.format(notificationTitleFormat, account.name),
message, PendingIntent.getActivity(
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
- .notify(getSigninRequiredNotificationId(account), n);
+ .notify(notificationId, n);
}
} finally {
restoreCallingIdentity(identityToken);
diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl
index a6ef6473..594c0e8 100755
--- a/core/java/android/os/IHardwareService.aidl
+++ b/core/java/android/os/IHardwareService.aidl
@@ -28,12 +28,6 @@
boolean getFlashlightEnabled();
void setFlashlightEnabled(boolean on);
void enableCameraFlash(int milliseconds);
-
- // sets the brightness of the backlights (screen, keyboard, button) 0-255
- void setBacklights(int brightness);
-
- // enables or disables automatic brightness mode
- void setAutoBrightness(boolean on);
// for the phone
void setAttentionLight(boolean on);
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 188e7ff..189335e 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -31,4 +31,10 @@
long getScreenOnTime();
void preventScreenOn(boolean prevent);
void setScreenBrightnessOverride(int brightness);
+
+ // sets the brightness of the backlights (screen, keyboard, button) 0-255
+ void setBacklightBrightness(int brightness);
+
+ // enables or disables automatic brightness mode
+ void setAutoBrightness(boolean on);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index d5934102..11c96d2 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -379,6 +379,21 @@
}
}
+ /**
+ * sets the brightness of the backlights (screen, keyboard, button).
+ *
+ * @param brightness value from 0 to 255
+ *
+ * {@hide}
+ */
+ public void setBacklightBrightness(int brightness)
+ {
+ try {
+ mService.setBacklightBrightness(brightness);
+ } catch (RemoteException e) {
+ }
+ }
+
/**
* Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
* that are supported on the device.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d354ccf..b0ac7f4 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -46,6 +46,15 @@
/** A content:// style uri to the authority for the contacts provider */
public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
+ /**
+ * An optional insert, update or delete URI parameter that allows the caller
+ * to specify that it is a sync adapter. The default value is false. If true
+ * the dirty flag is not automatically set and the "syncToNetwork" parameter
+ * is set to false when calling
+ * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}.
+ */
+ public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
+
public interface SyncStateColumns extends SyncStateContract.Columns {
}
@@ -480,7 +489,8 @@
* called on a raw contact, it is marked for deletion and removed from its
* aggregate contact. The sync adaptor deletes the raw contact on the server and
* then calls ContactResolver.delete once more, this time passing the
- * {@link RawContacts#DELETE_PERMANENTLY} query parameter to finalize the data removal.
+ * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
+ * the data removal.
* <P>Type: INTEGER</P>
*/
public static final String DELETED = "deleted";
@@ -517,14 +527,6 @@
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact";
/**
- * Query parameter that can be passed with the {@link #CONTENT_URI} URI
- * to the {@link android.content.ContentResolver#delete} method to
- * indicate that the raw contact can be deleted physically, rather than
- * merely marked as deleted.
- */
- public static final String DELETE_PERMANENTLY = "delete_permanently";
-
- /**
* Aggregation mode: aggregate asynchronously.
*/
public static final int AGGREGATION_MODE_DEFAULT = 0;
@@ -648,13 +650,6 @@
public static final String SYNC3 = "data_sync3";
/** Generic column for use by sync adapters. */
public static final String SYNC4 = "data_sync4";
-
- /**
- * An optional insert, update or delete URI parameter that determines if
- * the corresponding raw contact should be marked as dirty. The default
- * value is true.
- */
- public static final String MARK_AS_DIRTY = "mark_as_dirty";
}
/**
@@ -1533,8 +1528,9 @@
* for deletion. When {@link android.content.ContentResolver#delete} is
* called on a raw contact, it is marked for deletion and removed from its
* aggregate contact. The sync adaptor deletes the raw contact on the server and
- * then calls ContactResolver.delete once more, this time passing the
- * {@link RawContacts#DELETE_PERMANENTLY} query parameter to finalize the data removal.
+ * then calls ContactResolver.delete once more, this time setting the the
+ * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
+ * the data removal.
* <P>Type: INTEGER</P>
*/
public static final String DELETED = "deleted";
@@ -1579,20 +1575,6 @@
* The MIME type of a single group.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group";
-
- /**
- * Query parameter that can be passed with the {@link #CONTENT_URI} URI
- * to the {@link android.content.ContentResolver#delete} method to
- * indicate that the raw contact can be deleted physically, rather than
- * merely marked as deleted.
- */
- public static final String DELETE_PERMANENTLY = "delete_permanently";
-
- /**
- * An optional update or insert URI parameter that determines if the
- * group should be marked as dirty. The default value is true.
- */
- public static final String MARK_AS_DIRTY = "mark_as_dirty";
}
/**
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index a6d76d6..3f369dd 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -35,9 +35,13 @@
/**
*
* Synthesizes speech from text for immediate playback or to create a sound file.
+ * <p>A TextToSpeech instance can only be used to synthesize text once it has completed its
+ * initialization. Implement the {@link TextToSpeech.OnInitListener} to be
+ * notified of the completion of the initialization.<br>
+ * When you are done using the TextToSpeech instance, call the {@link #shutdown()} method
+ * to release the native resources used by the TextToSpeech engine.
*
*/
-//TODO complete javadoc + add links to constants
public class TextToSpeech {
/**
@@ -85,7 +89,7 @@
public static final int LANG_MISSING_DATA = -1;
/**
- * Denotes the language is not supported by the current TTS engine.
+ * Denotes the language is not supported.
*/
public static final int LANG_NOT_SUPPORTED = -2;
@@ -100,29 +104,38 @@
/**
- * Called when the TTS has initialized.
- *
- * The InitListener must implement the onInit function. onInit is passed a
- * status code indicating the result of the TTS initialization.
+ * Interface definition of a callback to be invoked indicating the completion of the
+ * TextToSpeech engine initialization.
*/
public interface OnInitListener {
+ /**
+ * Called to signal the completion of the TextToSpeech engine initialization.
+ * @param status {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}.
+ */
public void onInit(int status);
}
/**
- * Called when the TTS has completed saying something that has an utterance ID set.
+ * Interface definition of a callback to be invoked indicating the TextToSpeech engine has
+ * completed synthesizing an utterance with an utterance ID set.
*
- * The OnUtteranceCompletedListener must implement the onUtteranceCompleted function.
- * onUtteranceCompleted is passed a String that is the utteranceId given in
- * the original speak call.
*/
- public interface OnUtteranceCompletedListener {
+ public interface OnUtteranceCompletedListener {
+ /**
+ * Called to signal the completion of the synthesis of the utterance that was identified
+ * with the string parameter. This identifier is the one originally passed in the
+ * parameter hashmap of the synthesis request in
+ * {@link TextToSpeech#speak(String, int, HashMap)} or
+ * {@link TextToSpeech#synthesizeToFile(String, HashMap, String)} with the
+ * {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID} key.
+ * @param utteranceId the identifier of the utterance.
+ */
public void onUtteranceCompleted(String utteranceId);
}
/**
- * Internal constants for the TTS functionality
+ * Internal constants for the TextToSpeech functionality
*
*/
public class Engine {
@@ -145,38 +158,41 @@
public static final String DEFAULT_SYNTH = "com.svox.pico";
// default values for rendering
+ /**
+ * Default audio stream used when playing synthesized speech.
+ */
public static final int DEFAULT_STREAM = AudioManager.STREAM_MUSIC;
// return codes for a TTS engine's check data activity
/**
* Indicates success when checking the installation status of the resources used by the
- * text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+ * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_PASS = 1;
/**
* Indicates failure when checking the installation status of the resources used by the
- * text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+ * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_FAIL = 0;
/**
* Indicates erroneous data when checking the installation status of the resources used by
- * the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+ * the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_BAD_DATA = -1;
/**
* Indicates missing resources when checking the installation status of the resources used
- * by the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+ * by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_MISSING_DATA = -2;
/**
* Indicates missing storage volume when checking the installation status of the resources
- * used by the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+ * used by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3;
// intents to ask engine to install data or check its data
/**
- * Activity Action: Triggers the platform Text-To-Speech engine to
+ * Activity Action: Triggers the platform TextToSpeech engine to
* start the activity that installs the resource files on the device
* that are required for TTS to be operational. Since the installation
* of the data can be interrupted or declined by the user, the application
@@ -197,7 +213,7 @@
public static final String ACTION_TTS_DATA_INSTALLED =
"android.speech.tts.engine.TTS_DATA_INSTALLED";
/**
- * Activity Action: Starts the activity from the platform Text-To-Speech
+ * Activity Action: Starts the activity from the platform TextToSpeech
* engine to verify the proper installation and availability of the
* resource files on the system. Upon completion, the activity will
* return one of the following codes:
@@ -210,9 +226,9 @@
* fields:
* <ul>
* <li>{@link #EXTRA_VOICE_DATA_ROOT_DIRECTORY} which
- * indicates the path to the location of the resource files</li>,
+ * indicates the path to the location of the resource files,</li>
* <li>{@link #EXTRA_VOICE_DATA_FILES} which contains
- * the list of all the resource files</li>,
+ * the list of all the resource files,</li>
* <li>and {@link #EXTRA_VOICE_DATA_FILES_INFO} which
* contains, for each resource file, the description of the language covered by
* the file in the xxx-YYY format, where xxx is the 3-letter ISO language code,
@@ -226,18 +242,18 @@
// extras for a TTS engine's check data activity
/**
* Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
- * the text-to-speech engine specifies the path to its resources.
+ * the TextToSpeech engine specifies the path to its resources.
*/
public static final String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
/**
* Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
- * the text-to-speech engine specifies the file names of its resources under the
+ * the TextToSpeech engine specifies the file names of its resources under the
* resource path.
*/
public static final String EXTRA_VOICE_DATA_FILES = "dataFiles";
/**
* Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
- * the text-to-speech engine specifies the locale associated with each resource file.
+ * the TextToSpeech engine specifies the locale associated with each resource file.
*/
public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
@@ -272,11 +288,17 @@
/**
* Parameter key to specify the audio stream type to be used when speaking text
* or playing back a file.
+ * @see TextToSpeech#speak(String, int, HashMap)
+ * @see TextToSpeech#playEarcon(String, int, HashMap)
*/
public static final String KEY_PARAM_STREAM = "streamType";
/**
- * Parameter key to identify an utterance in the completion listener after text has been
+ * Parameter key to identify an utterance in the
+ * {@link TextToSpeech.OnUtteranceCompletedListener} after text has been
* spoken, a file has been played back or a silence duration has elapsed.
+ * @see TextToSpeech#speak(String, int, HashMap)
+ * @see TextToSpeech#playEarcon(String, int, HashMap)
+ * @see TextToSpeech#synthesizeToFile(String, HashMap, String)
*/
public static final String KEY_PARAM_UTTERANCE_ID = "utteranceId";
@@ -330,13 +352,14 @@
private String[] mCachedParams;
/**
- * The constructor for the TTS.
+ * The constructor for the TextToSpeech class.
+ * This will also initialize the associated TextToSpeech engine if it isn't already running.
*
* @param context
- * The context
+ * The context this instance is running in.
* @param listener
- * The InitListener that will be called when the TTS has
- * initialized successfully.
+ * The {@link TextToSpeech.OnInitListener} that will be called when the
+ * TextToSpeech engine has initialized.
*/
public TextToSpeech(Context context, OnInitListener listener) {
mContext = context;
@@ -402,9 +425,9 @@
/**
- * Shuts down the TTS. It is good practice to call this in the onDestroy
- * method of the Activity that is using the TTS so that the TTS is stopped
- * cleanly.
+ * Releases the resources used by the TextToSpeech engine.
+ * It is good practice for instance to call this method in the onDestroy() method of an Activity
+ * so the TextToSpeech engine can be cleanly stopped.
*/
public void shutdown() {
try {
@@ -418,11 +441,12 @@
/**
* Adds a mapping between a string of text and a sound resource in a
- * package.
- * @see #speak(String, int, HashMap)
+ * package. After a call to this method, subsequent calls to
+ * {@link #speak(String, int, HashMap)} will play the specified sound resource
+ * if it is available, or synthesize the text it is missing.
*
* @param text
- * Example: <b><code>"south_south_east"</code></b><br/>
+ * The string of text. Example: <code>"south_south_east"</code>
*
* @param packagename
* Pass the packagename of the application that contains the
@@ -438,7 +462,7 @@
* </p>
*
* @param resourceId
- * Example: <b><code>R.raw.south_south_east</code></b>
+ * Example: <code>R.raw.south_south_east</code>
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
@@ -476,10 +500,13 @@
/**
* Adds a mapping between a string of text and a sound file. Using this, it
- * is possible to add custom pronounciations for text.
+ * is possible to add custom pronounciations for a string of text.
+ * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)}
+ * will play the specified sound resource if it is available, or synthesize the text it is
+ * missing.
*
* @param text
- * The string of text
+ * The string of text. Example: <code>"south_south_east"</code>
* @param filename
* The full path to the sound file (for example:
* "/sdcard/mysounds/hello.wav")
@@ -520,28 +547,26 @@
/**
* Adds a mapping between a string of text and a sound resource in a
- * package.
+ * package. Use this to add custom earcons.
*
* @see #playEarcon(String, int, HashMap)
*
- * @param earcon The name of the earcon
- * Example: <b><code>"[tick]"</code></b><br/>
+ * @param earcon The name of the earcon.
+ * Example: <code>"[tick]"</code><br/>
*
* @param packagename
- * Pass the packagename of the application that contains the
- * resource. If the resource is in your own application (this is
- * the most common case), then put the packagename of your
- * application here.<br/>
+ * the package name of the application that contains the
+ * resource. This can for instance be the package name of your own application.
* Example: <b>"com.google.marvin.compass"</b><br/>
- * The packagename can be found in the AndroidManifest.xml of
- * your application.
+ * The package name can be found in the AndroidManifest.xml of
+ * the application containing the resource.
* <p>
* <code><manifest xmlns:android="..."
* package="<b>com.google.marvin.compass</b>"></code>
* </p>
*
* @param resourceId
- * Example: <b><code>R.raw.tick_snd</code></b>
+ * Example: <code>R.raw.tick_snd</code>
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
@@ -578,11 +603,14 @@
/**
- * Adds a mapping between a string of text and a sound file. Using this, it
- * is possible to add custom earcons.
+ * Adds a mapping between a string of text and a sound file.
+ * Use this to add custom earcons.
+ *
+ * @see #playEarcon(String, int, HashMap)
*
* @param earcon
- * The name of the earcon
+ * The name of the earcon.
+ * Example: <code>"[tick]"</code>
* @param filename
* The full path to the sound file (for example:
* "/sdcard/mysounds/tick.wav")
@@ -623,18 +651,18 @@
/**
* Speaks the string using the specified queuing strategy and speech
- * parameters. Note that the speech parameters are not universally supported
- * by all engines and will be treated as a hint. The TTS library will try to
- * fulfill these parameters as much as possible, but there is no guarantee
- * that the voice used will have the properties specified.
+ * parameters.
*
* @param text
* The string of text to be spoken.
* @param queueMode
* The queuing strategy to use.
- * See QUEUE_ADD and QUEUE_FLUSH.
+ * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
* @param params
- * The hashmap of speech parameters to be used.
+ * The list of parameters to be used. Can be null if no parameters are given.
+ * They are specified using a (key, value) pair, where the key can be
+ * {@link Engine#KEY_PARAM_STREAM} or
+ * {@link Engine#KEY_PARAM_UTTERANCE_ID}.
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
@@ -690,9 +718,12 @@
* @param earcon
* The earcon that should be played
* @param queueMode
- * See QUEUE_ADD and QUEUE_FLUSH.
+ * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
* @param params
- * The hashmap of parameters to be used.
+ * The list of parameters to be used. Can be null if no parameters are given.
+ * They are specified using a (key, value) pair, where the key can be
+ * {@link Engine#KEY_PARAM_STREAM} or
+ * {@link Engine#KEY_PARAM_UTTERANCE_ID}.
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
@@ -747,7 +778,11 @@
* @param durationInMs
* A long that indicates how long the silence should last.
* @param queueMode
- * See QUEUE_ADD and QUEUE_FLUSH.
+ * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
+ * @param params
+ * The list of parameters to be used. Can be null if no parameters are given.
+ * They are specified using a (key, value) pair, where the key can be
+ * {@link Engine#KEY_PARAM_UTTERANCE_ID}.
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
@@ -791,9 +826,9 @@
/**
- * Returns whether or not the TTS is busy speaking.
+ * Returns whether or not the TextToSpeech engine is busy speaking.
*
- * @return Whether or not the TTS is busy speaking.
+ * @return Whether or not the TextToSpeech engine is busy speaking.
*/
public boolean isSpeaking() {
synchronized (mStartLock) {
@@ -827,7 +862,8 @@
/**
- * Stops speech from the TTS.
+ * Interrupts the current utterance (whether played or rendered to file) and discards other
+ * utterances in the queue.
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
@@ -865,15 +901,12 @@
/**
- * Sets the speech rate for the TTS engine.
+ * Sets the speech rate for the TextToSpeech engine.
*
- * Note that the speech rate is not universally supported by all engines and
- * will be treated as a hint. The TTS library will try to use the specified
- * speech rate, but there is no guarantee.
* This has no effect on any pre-recorded speech.
*
* @param speechRate
- * The speech rate for the TTS engine. 1 is the normal speed,
+ * The speech rate for the TextToSpeech engine. 1 is the normal speed,
* lower values slow down the speech (0.5 is half the normal speech rate),
* greater values accelerate it (2 is twice the normal speech rate).
*
@@ -917,15 +950,12 @@
/**
- * Sets the speech pitch for the TTS engine.
+ * Sets the speech pitch for the TextToSpeech engine.
*
- * Note that the pitch is not universally supported by all engines and
- * will be treated as a hint. The TTS library will try to use the specified
- * pitch, but there is no guarantee.
* This has no effect on any pre-recorded speech.
*
* @param pitch
- * The pitch for the TTS engine. 1 is the normal pitch,
+ * The pitch for the TextToSpeech engine. 1 is the normal pitch,
* lower values lower the tone of the synthesized voice,
* greater values increase it.
*
@@ -967,11 +997,11 @@
/**
- * Sets the language for the TTS engine.
- *
- * Note that the language is not universally supported by all engines and
- * will be treated as a hint. The TTS library will try to use the specified
- * language as represented by the Locale, but there is no guarantee.
+ * Sets the language for the TextToSpeech engine.
+ * The TextToSpeech engine will try to use the closest match to the specified
+ * language as represented by the Locale, but there is no guarantee that the exact same Locale
+ * will be used. Use {@link #isLanguageAvailable(Locale)} to check the level of support
+ * before choosing the language to use for the next utterances.
*
* @param loc
* The locale describing the language to be used.
@@ -1023,9 +1053,10 @@
/**
- * Returns a Locale instance describing the language currently being used by the TTS engine.
+ * Returns a Locale instance describing the language currently being used by the TextToSpeech
+ * engine.
* @return language, country (if any) and variant (if any) used by the engine stored in a Locale
- * instance, or null is the TTS engine has failed.
+ * instance, or null is the TextToSpeech engine has failed.
*/
public Locale getLanguage() {
synchronized (mStartLock) {
@@ -1063,7 +1094,7 @@
}
/**
- * Checks if the specified language as represented by the Locale is available.
+ * Checks if the specified language as represented by the Locale is available and supported.
*
* @param loc
* The Locale describing the language to be used.
@@ -1112,7 +1143,9 @@
* @param text
* The String of text that should be synthesized
* @param params
- * A hashmap of parameters.
+ * The list of parameters to be used. Can be null if no parameters are given.
+ * They are specified using a (key, value) pair, where the key can be
+ * {@link Engine#KEY_PARAM_UTTERANCE_ID}.
* @param filename
* The string that gives the full output filename; it should be
* something like "/sdcard/myappsounds/mysound.wav".
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1426aef..356f55a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -236,6 +236,10 @@
@Override
public boolean gatherTransparentRegion(Region region) {
+ if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ return super.gatherTransparentRegion(region);
+ }
+
boolean opaque = true;
if ((mPrivateFlags & SKIP_DRAW) == 0) {
// this view draws, remove it from the transparent region
@@ -259,20 +263,24 @@
@Override
public void draw(Canvas canvas) {
- // draw() is not called when SKIP_DRAW is set
- if ((mPrivateFlags & SKIP_DRAW) == 0) {
- // punch a whole in the view-hierarchy below us
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ // draw() is not called when SKIP_DRAW is set
+ if ((mPrivateFlags & SKIP_DRAW) == 0) {
+ // punch a whole in the view-hierarchy below us
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ }
}
super.draw(canvas);
}
@Override
protected void dispatchDraw(Canvas canvas) {
- // if SKIP_DRAW is cleared, draw() has already punched a hole
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- // punch a whole in the view-hierarchy below us
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ // if SKIP_DRAW is cleared, draw() has already punched a hole
+ if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+ // punch a whole in the view-hierarchy below us
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ }
}
// reposition ourselves where the surface is
mHaveFrame = true;
@@ -281,6 +289,22 @@
}
/**
+ * Control whether the surface view's surface is placed on top of its
+ * window. Normally it is placed behind the window, to allow it to
+ * (for the most part) appear to composite with the views in the
+ * hierarchy. By setting this, you cause it to be placed above the
+ * window. This means that none of the contents of the window this
+ * SurfaceView is in will be visible on top of its surface.
+ *
+ * <p>Note that this must be set before the surface view's containing
+ * window is attached to the window manager.
+ */
+ public void setOnTop(boolean onTop) {
+ mWindowType = onTop ? WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
+ : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+ }
+
+ /**
* Hack to allow special layering of windows. The type is one of the
* types in WindowManager.LayoutParams. This is a hack so:
* @hide
@@ -345,7 +369,9 @@
}
mLayout.format = mRequestedFormat;
- mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_SCALED
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index db6b74f..465eef8 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -222,7 +222,6 @@
private void resetLoadingStates() {
mCommitted = true;
- mWebViewCore.mEndScaleZoom = mFirstLayoutDone == false;
mFirstLayoutDone = true;
}
@@ -245,7 +244,6 @@
// blocking the update in {@link #loadStarted}
mWebViewCore.contentDraw();
}
- mWebViewCore.mEndScaleZoom = true;
}
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2329e21..081f67a 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -25,8 +25,6 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
import android.graphics.Picture;
import android.graphics.Point;
import android.graphics.Rect;
@@ -59,7 +57,6 @@
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.animation.AlphaAnimation;
-import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebTextView.AutoCompleteAdapter;
import android.webkit.WebViewCore.EventHub;
@@ -68,9 +65,7 @@
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.ListView;
-import android.widget.ScrollBarDrawable;
import android.widget.Scroller;
import android.widget.Toast;
import android.widget.ZoomButtonsController;
@@ -219,13 +214,13 @@
inflater.inflate(com.android.internal.R.layout.zoom_magnify, this, true);
mPlusMinusZoomControls = (ZoomControls) findViewById(
com.android.internal.R.id.zoomControls);
- mZoomMagnify = (ImageView) findViewById(com.android.internal.R.id.zoomMagnify);
+ findViewById(com.android.internal.R.id.zoomMagnify).setVisibility(
+ View.GONE);
}
public void show(boolean showZoom, boolean canZoomOut) {
mPlusMinusZoomControls.setVisibility(
showZoom ? View.VISIBLE : View.GONE);
- mZoomMagnify.setVisibility(canZoomOut ? View.VISIBLE : View.GONE);
fade(View.VISIBLE, 0.0f, 1.0f);
}
@@ -240,12 +235,8 @@
setVisibility(visibility);
}
- public void setIsZoomMagnifyEnabled(boolean isEnabled) {
- mZoomMagnify.setEnabled(isEnabled);
- }
-
public boolean hasFocus() {
- return mPlusMinusZoomControls.hasFocus() || mZoomMagnify.hasFocus();
+ return mPlusMinusZoomControls.hasFocus();
}
public void setOnZoomInClickListener(OnClickListener listener) {
@@ -256,12 +247,7 @@
mPlusMinusZoomControls.setOnZoomOutClickListener(listener);
}
- public void setOnZoomMagnifyClickListener(OnClickListener listener) {
- mZoomMagnify.setOnClickListener(listener);
- }
-
ZoomControls mPlusMinusZoomControls;
- ImageView mZoomMagnify;
}
/**
@@ -351,9 +337,6 @@
private float mLastVelX;
private float mLastVelY;
- // use this flag to control whether enabling the new double tap zoom
- static final boolean ENABLE_DOUBLETAP_ZOOM = true;
-
/**
* Touch mode
*/
@@ -363,17 +346,9 @@
private static final int TOUCH_DRAG_MODE = 3;
private static final int TOUCH_SHORTPRESS_START_MODE = 4;
private static final int TOUCH_SHORTPRESS_MODE = 5;
- private static final int TOUCH_DOUBLECLICK_MODE = 6;
+ private static final int TOUCH_DOUBLE_TAP_MODE = 6;
private static final int TOUCH_DONE_MODE = 7;
private static final int TOUCH_SELECT_MODE = 8;
- // touch mode values specific to scale+scroll
- private static final int FIRST_SCROLL_ZOOM = 9;
- private static final int SCROLL_ZOOM_ANIMATION_IN = 9;
- private static final int SCROLL_ZOOM_ANIMATION_OUT = 10;
- private static final int SCROLL_ZOOM_OUT = 11;
- private static final int LAST_SCROLL_ZOOM = 11;
- // end of touch mode values specific to scale+scroll
- private static final int TOUCH_DOUBLE_TAP_MODE = 12;
// Whether to forward the touch events to WebCore
private boolean mForwardTouchEvents = false;
@@ -1835,23 +1810,50 @@
return contentToViewDimension(y) + getTitleHeight();
}
+ private Rect contentToViewRect(Rect x) {
+ return new Rect(contentToViewX(x.left), contentToViewY(x.top),
+ contentToViewX(x.right), contentToViewY(x.bottom));
+ }
+
+ /* To invalidate a rectangle in content coordinates, we need to transform
+ the rect into view coordinates, so we can then call invalidate(...).
+
+ Normally, we would just call contentToView[XY](...), which eventually
+ calls Math.round(coordinate * mActualScale). However, for invalidates,
+ we need to account for the slop that occurs with antialiasing. To
+ address that, we are a little more liberal in the size of the rect that
+ we invalidate.
+
+ This liberal calculation calls floor() for the top/left, and ceil() for
+ the bottom/right coordinates. This catches the possible extra pixels of
+ antialiasing that we might have missed with just round().
+ */
+
// Called by JNI to invalidate the View, given rectangle coordinates in
// content space
private void viewInvalidate(int l, int t, int r, int b) {
- invalidate(contentToViewX(l), contentToViewY(t), contentToViewX(r),
- contentToViewY(b));
+ final float scale = mActualScale;
+ final int dy = getTitleHeight();
+ invalidate((int)Math.floor(l * scale),
+ (int)Math.floor(t * scale) + dy,
+ (int)Math.ceil(r * scale),
+ (int)Math.ceil(b * scale) + dy);
}
// Called by JNI to invalidate the View after a delay, given rectangle
// coordinates in content space
private void viewInvalidateDelayed(long delay, int l, int t, int r, int b) {
- postInvalidateDelayed(delay, contentToViewX(l), contentToViewY(t),
- contentToViewX(r), contentToViewY(b));
+ final float scale = mActualScale;
+ final int dy = getTitleHeight();
+ postInvalidateDelayed(delay,
+ (int)Math.floor(l * scale),
+ (int)Math.floor(t * scale) + dy,
+ (int)Math.ceil(r * scale),
+ (int)Math.ceil(b * scale) + dy);
}
- private Rect contentToView(Rect x) {
- return new Rect(contentToViewX(x.left), contentToViewY(x.top)
- , contentToViewX(x.right), contentToViewY(x.bottom));
+ private void invalidateContentRect(Rect r) {
+ viewInvalidate(r.left, r.top, r.right, r.bottom);
}
// stop the scroll animation, and don't let a subsequent fling add
@@ -2675,32 +2677,19 @@
if (mNativeClass == 0) {
return;
}
- if (mWebViewCore.mEndScaleZoom) {
- mWebViewCore.mEndScaleZoom = false;
- if (mTouchMode >= FIRST_SCROLL_ZOOM
- && mTouchMode <= LAST_SCROLL_ZOOM) {
- setHorizontalScrollBarEnabled(true);
- setVerticalScrollBarEnabled(true);
- mTouchMode = TOUCH_DONE_MODE;
- }
- }
canvas.save();
- if (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM) {
- scrollZoomDraw(canvas);
- } else {
- // Update the buttons in the picture, so when we draw the picture
- // to the screen, they are in the correct state.
- // Tell the native side if user is a) touching the screen,
- // b) pressing the trackball down, or c) pressing the enter key
- // If the cursor is on a button, we need to draw it in the pressed
- // state.
- // If mNativeClass is 0, we should not reach here, so we do not
- // need to check it again.
- nativeRecordButtons(hasFocus() && hasWindowFocus(),
- mTouchMode == TOUCH_SHORTPRESS_START_MODE
- || mTrackballDown || mGotCenterDown, false);
- drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing);
- }
+ // Update the buttons in the picture, so when we draw the picture
+ // to the screen, they are in the correct state.
+ // Tell the native side if user is a) touching the screen,
+ // b) pressing the trackball down, or c) pressing the enter key
+ // If the cursor is on a button, we need to draw it in the pressed
+ // state.
+ // If mNativeClass is 0, we should not reach here, so we do not
+ // need to check it again.
+ nativeRecordButtons(hasFocus() && hasWindowFocus(),
+ mTouchMode == TOUCH_SHORTPRESS_START_MODE
+ || mTrackballDown || mGotCenterDown, false);
+ drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing);
canvas.restoreToCount(saveCount);
if (AUTO_REDRAW_HACK && mAutoRedraw) {
@@ -2765,13 +2754,14 @@
zoomScale = mZoomScale;
// set mZoomScale to be 0 as we have done animation
mZoomScale = 0;
+ animateZoom = false; // inform drawContentPicture we're done
if (mNeedToAdjustWebTextView) {
mNeedToAdjustWebTextView = false;
mWebTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
contentToViewDimension(
nativeFocusCandidateTextSize()));
Rect bounds = nativeFocusCandidateNodeBounds();
- Rect vBox = contentToView(bounds);
+ Rect vBox = contentToViewRect(bounds);
mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
vBox.height());
// If it is a password field, start drawing the
@@ -2838,371 +2828,6 @@
}
}
- private float scrollZoomGridScale(float invScale) {
- float griddedInvScale = (int) (invScale * SCROLL_ZOOM_GRID)
- / (float) SCROLL_ZOOM_GRID;
- return 1.0f / griddedInvScale;
- }
-
- private float scrollZoomX(float scale) {
- int width = getViewWidth();
- float maxScrollZoomX = mContentWidth * scale - width;
- int maxX = mContentWidth - width;
- return -(maxScrollZoomX > 0 ? mZoomScrollX * maxScrollZoomX / maxX
- : maxScrollZoomX / 2);
- }
-
- private float scrollZoomY(float scale) {
- int height = getViewHeight();
- float maxScrollZoomY = mContentHeight * scale - height;
- int maxY = mContentHeight - height;
- return -(maxScrollZoomY > 0 ? mZoomScrollY * maxScrollZoomY / maxY
- : maxScrollZoomY / 2);
- }
-
- private void drawMagnifyFrame(Canvas canvas, Rect frame, Paint paint) {
- final float ADORNMENT_LEN = 16.0f;
- float width = frame.width();
- float height = frame.height();
- Path path = new Path();
- path.moveTo(-ADORNMENT_LEN, -ADORNMENT_LEN);
- path.lineTo(0, 0);
- path.lineTo(width, 0);
- path.lineTo(width + ADORNMENT_LEN, -ADORNMENT_LEN);
- path.moveTo(-ADORNMENT_LEN, height + ADORNMENT_LEN);
- path.lineTo(0, height);
- path.lineTo(width, height);
- path.lineTo(width + ADORNMENT_LEN, height + ADORNMENT_LEN);
- path.moveTo(0, 0);
- path.lineTo(0, height);
- path.moveTo(width, 0);
- path.lineTo(width, height);
- path.offset(frame.left, frame.top);
- canvas.drawPath(path, paint);
- }
-
- // Returns frame surrounding magified portion of screen while
- // scroll-zoom is enabled. The frame is also used to center the
- // zoom-in zoom-out points at the start and end of the animation.
- private Rect scrollZoomFrame(int width, int height, float halfScale) {
- Rect scrollFrame = new Rect();
- scrollFrame.set(mZoomScrollX, mZoomScrollY,
- mZoomScrollX + width, mZoomScrollY + height);
- if (mContentWidth * mZoomScrollLimit < width) {
- float scale = zoomFrameScaleX(width, halfScale, 1.0f);
- float offsetX = (width * scale - width) * 0.5f;
- scrollFrame.left -= offsetX;
- scrollFrame.right += offsetX;
- }
- if (mContentHeight * mZoomScrollLimit < height) {
- float scale = zoomFrameScaleY(height, halfScale, 1.0f);
- float offsetY = (height * scale - height) * 0.5f;
- scrollFrame.top -= offsetY;
- scrollFrame.bottom += offsetY;
- }
- return scrollFrame;
- }
-
- private float zoomFrameScaleX(int width, float halfScale, float noScale) {
- // mContentWidth > width > mContentWidth * mZoomScrollLimit
- if (mContentWidth <= width) {
- return halfScale;
- }
- float part = (width - mContentWidth * mZoomScrollLimit)
- / (width * (1 - mZoomScrollLimit));
- return halfScale * part + noScale * (1.0f - part);
- }
-
- private float zoomFrameScaleY(int height, float halfScale, float noScale) {
- if (mContentHeight <= height) {
- return halfScale;
- }
- float part = (height - mContentHeight * mZoomScrollLimit)
- / (height * (1 - mZoomScrollLimit));
- return halfScale * part + noScale * (1.0f - part);
- }
-
- private float scrollZoomMagScale(float invScale) {
- return (invScale * 2 + mInvActualScale) / 3;
- }
-
- private void scrollZoomDraw(Canvas canvas) {
- float invScale = mZoomScrollInvLimit;
- int elapsed = 0;
- if (mTouchMode != SCROLL_ZOOM_OUT) {
- elapsed = (int) Math.min(System.currentTimeMillis()
- - mZoomScrollStart, SCROLL_ZOOM_DURATION);
- float transitionScale = (mZoomScrollInvLimit - mInvActualScale)
- * elapsed / SCROLL_ZOOM_DURATION;
- if (mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
- invScale = mInvActualScale + transitionScale;
- } else { /* if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN) */
- invScale = mZoomScrollInvLimit - transitionScale;
- }
- }
- float scale = scrollZoomGridScale(invScale);
- invScale = 1.0f / scale;
- int width = getViewWidth();
- int height = getViewHeight();
- float halfScale = scrollZoomMagScale(invScale);
- Rect scrollFrame = scrollZoomFrame(width, height, halfScale);
- if (elapsed == SCROLL_ZOOM_DURATION) {
- if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN) {
- setHorizontalScrollBarEnabled(true);
- setVerticalScrollBarEnabled(true);
- rebuildWebTextView();
- scrollTo((int) (scrollFrame.centerX() * mActualScale)
- - (width >> 1), (int) (scrollFrame.centerY()
- * mActualScale) - (height >> 1));
- mTouchMode = TOUCH_DONE_MODE;
- // Show all the child views once we are done.
- mViewManager.showAll();
- } else {
- mTouchMode = SCROLL_ZOOM_OUT;
- }
- }
- float newX = scrollZoomX(scale);
- float newY = scrollZoomY(scale);
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "scrollZoomDraw scale=" + scale + " + (" + newX
- + ", " + newY + ") mZoomScroll=(" + mZoomScrollX + ", "
- + mZoomScrollY + ")" + " invScale=" + invScale + " scale="
- + scale);
- }
- canvas.translate(newX, newY);
- canvas.scale(scale, scale);
- boolean animating = mTouchMode != SCROLL_ZOOM_OUT;
- if (mDrawHistory) {
- int sc = canvas.save(Canvas.CLIP_SAVE_FLAG);
- Rect clip = new Rect(0, 0, mHistoryPicture.getWidth(),
- mHistoryPicture.getHeight());
- canvas.clipRect(clip, Region.Op.DIFFERENCE);
- canvas.drawColor(mBackgroundColor);
- canvas.restoreToCount(sc);
- canvas.drawPicture(mHistoryPicture);
- } else {
- mWebViewCore.drawContentPicture(canvas, mBackgroundColor,
- animating, true);
- }
- if (mTouchMode == TOUCH_DONE_MODE) {
- return;
- }
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(30.0f);
- paint.setARGB(0x50, 0, 0, 0);
- int maxX = mContentWidth - width;
- int maxY = mContentHeight - height;
- if (true) { // experiment: draw hint to place finger off magnify area
- drawMagnifyFrame(canvas, scrollFrame, paint);
- } else {
- canvas.drawRect(scrollFrame, paint);
- }
- int sc = canvas.save();
- canvas.clipRect(scrollFrame);
- float halfX = (float) mZoomScrollX / maxX;
- if (mContentWidth * mZoomScrollLimit < width) {
- halfX = zoomFrameScaleX(width, 0.5f, halfX);
- }
- float halfY = (float) mZoomScrollY / maxY;
- if (mContentHeight * mZoomScrollLimit < height) {
- halfY = zoomFrameScaleY(height, 0.5f, halfY);
- }
- canvas.scale(halfScale, halfScale, mZoomScrollX + width * halfX
- , mZoomScrollY + height * halfY);
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "scrollZoomDraw halfScale=" + halfScale + " w/h=("
- + width + ", " + height + ") half=(" + halfX + ", "
- + halfY + ")");
- }
- if (mDrawHistory) {
- canvas.drawPicture(mHistoryPicture);
- } else {
- mWebViewCore.drawContentPicture(canvas, mBackgroundColor,
- animating, false);
- }
- canvas.restoreToCount(sc);
- if (mTouchMode != SCROLL_ZOOM_OUT) {
- invalidate();
- }
- }
-
- private void zoomScrollTap(float x, float y) {
- float scale = scrollZoomGridScale(mZoomScrollInvLimit);
- float left = scrollZoomX(scale);
- float top = scrollZoomY(scale);
- int width = getViewWidth();
- int height = getViewHeight();
- x -= width * scale / 2;
- y -= height * scale / 2;
- mZoomScrollX = Math.min(mContentWidth - width
- , Math.max(0, (int) ((x - left) / scale)));
- mZoomScrollY = Math.min(mContentHeight - height
- , Math.max(0, (int) ((y - top) / scale)));
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "zoomScrollTap scale=" + scale + " + (" + left
- + ", " + top + ") mZoomScroll=(" + mZoomScrollX + ", "
- + mZoomScrollY + ")" + " x=" + x + " y=" + y);
- }
- }
-
- /**
- * @hide
- */
- public boolean canZoomScrollOut() {
- if (mContentWidth == 0 || mContentHeight == 0) {
- return false;
- }
- int width = getViewWidth();
- int height = getViewHeight();
- float x = (float) width / (float) mContentWidth;
- float y = (float) height / (float) mContentHeight;
- mZoomScrollLimit = Math.max(DEFAULT_MIN_ZOOM_SCALE, Math.min(x, y));
- mZoomScrollInvLimit = 1.0f / mZoomScrollLimit;
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "canZoomScrollOut"
- + " mInvActualScale=" + mInvActualScale
- + " mZoomScrollLimit=" + mZoomScrollLimit
- + " mZoomScrollInvLimit=" + mZoomScrollInvLimit
- + " mContentWidth=" + mContentWidth
- + " mContentHeight=" + mContentHeight
- );
- }
- // don't zoom out unless magnify area is at least half as wide
- // or tall as content
- float limit = mZoomScrollLimit * 2;
- return mContentWidth >= width * limit
- || mContentHeight >= height * limit;
- }
-
- private void startZoomScrollOut() {
- setHorizontalScrollBarEnabled(false);
- setVerticalScrollBarEnabled(false);
- if (getSettings().getBuiltInZoomControls()) {
- if (mZoomButtonsController.isVisible()) {
- mZoomButtonsController.setVisible(false);
- }
- } else {
- if (mZoomControlRunnable != null) {
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- }
- if (mZoomControls != null) {
- mZoomControls.hide();
- }
- }
- int width = getViewWidth();
- int height = getViewHeight();
- int halfW = width >> 1;
- mLastTouchX = halfW;
- int halfH = height >> 1;
- mLastTouchY = halfH;
- abortAnimation();
- mZoomScrollStart = System.currentTimeMillis();
- Rect zoomFrame = scrollZoomFrame(width, height
- , scrollZoomMagScale(mZoomScrollInvLimit));
- mZoomScrollX = Math.max(0, (int) ((mScrollX + halfW) * mInvActualScale)
- - (zoomFrame.width() >> 1));
- mZoomScrollY = Math.max(0, (int) ((mScrollY + halfH) * mInvActualScale)
- - (zoomFrame.height() >> 1));
- scrollTo(0, 0); // triggers inval, starts animation
- clearTextEntry();
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "startZoomScrollOut mZoomScroll=("
- + mZoomScrollX + ", " + mZoomScrollY +")");
- }
- }
-
- /**
- * @hide
- */
- public void zoomScrollOut() {
- if (canZoomScrollOut() == false) {
- mTouchMode = TOUCH_DONE_MODE;
- return;
- }
- // Hide the child views while in this mode.
- mViewManager.hideAll();
- startZoomScrollOut();
- mTouchMode = SCROLL_ZOOM_ANIMATION_OUT;
- invalidate();
- }
-
- private void moveZoomScrollWindow(float x, float y) {
- if (Math.abs(x - mLastZoomScrollRawX) < 1.5f
- && Math.abs(y - mLastZoomScrollRawY) < 1.5f) {
- return;
- }
- mLastZoomScrollRawX = x;
- mLastZoomScrollRawY = y;
- int oldX = mZoomScrollX;
- int oldY = mZoomScrollY;
- int width = getViewWidth();
- int height = getViewHeight();
- int maxZoomX = mContentWidth - width;
- if (maxZoomX > 0) {
- int maxScreenX = width - (int) Math.ceil(width
- * mZoomScrollLimit) - SCROLL_ZOOM_FINGER_BUFFER;
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "moveZoomScrollWindow-X"
- + " maxScreenX=" + maxScreenX + " width=" + width
- + " mZoomScrollLimit=" + mZoomScrollLimit + " x=" + x);
- }
- x += maxScreenX * mLastScrollX / maxZoomX - mLastTouchX;
- x *= Math.max(maxZoomX / maxScreenX, mZoomScrollInvLimit);
- mZoomScrollX = Math.max(0, Math.min(maxZoomX, (int) x));
- }
- int maxZoomY = mContentHeight - height;
- if (maxZoomY > 0) {
- int maxScreenY = height - (int) Math.ceil(height
- * mZoomScrollLimit) - SCROLL_ZOOM_FINGER_BUFFER;
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "moveZoomScrollWindow-Y"
- + " maxScreenY=" + maxScreenY + " height=" + height
- + " mZoomScrollLimit=" + mZoomScrollLimit + " y=" + y);
- }
- y += maxScreenY * mLastScrollY / maxZoomY - mLastTouchY;
- y *= Math.max(maxZoomY / maxScreenY, mZoomScrollInvLimit);
- mZoomScrollY = Math.max(0, Math.min(maxZoomY, (int) y));
- }
- if (oldX != mZoomScrollX || oldY != mZoomScrollY) {
- invalidate();
- }
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "moveZoomScrollWindow"
- + " scrollTo=(" + mZoomScrollX + ", " + mZoomScrollY + ")"
- + " mLastTouch=(" + mLastTouchX + ", " + mLastTouchY + ")"
- + " maxZoom=(" + maxZoomX + ", " + maxZoomY + ")"
- + " last=("+mLastScrollX+", "+mLastScrollY+")"
- + " x=" + x + " y=" + y);
- }
- }
-
- private void setZoomScrollIn() {
- mZoomScrollStart = System.currentTimeMillis();
- }
-
- private float mZoomScrollLimit;
- private float mZoomScrollInvLimit;
- private int mLastScrollX;
- private int mLastScrollY;
- private long mZoomScrollStart;
- private int mZoomScrollX;
- private int mZoomScrollY;
- private float mLastZoomScrollRawX = -1000.0f;
- private float mLastZoomScrollRawY = -1000.0f;
- // The zoomed scale varies from 1.0 to DEFAULT_MIN_ZOOM_SCALE == 0.25.
- // The zoom animation duration SCROLL_ZOOM_DURATION == 0.5.
- // Two pressures compete for gridding; a high frame rate (e.g. 20 fps)
- // and minimizing font cache allocations (fewer frames is better).
- // A SCROLL_ZOOM_GRID of 6 permits about 20 zoom levels over 0.5 seconds:
- // the inverse of: 1.0, 1.16, 1.33, 1.5, 1.67, 1.84, 2.0, etc. to 4.0
- private static final int SCROLL_ZOOM_GRID = 6;
- private static final int SCROLL_ZOOM_DURATION = 500;
- // Make it easier to get to the bottom of a document by reserving a 32
- // pixel buffer, for when the starting drag is a bit below the bottom of
- // the magnify frame.
- private static final int SCROLL_ZOOM_FINGER_BUFFER = 32;
-
// draw history
private boolean mDrawHistory = false;
private Picture mHistoryPicture = null;
@@ -3312,9 +2937,7 @@
*/
/* package */ void rebuildWebTextView() {
// If the WebView does not have focus, do nothing until it gains focus.
- if (!hasFocus() && (null == mWebTextView || !mWebTextView.hasFocus())
- || (mTouchMode >= FIRST_SCROLL_ZOOM
- && mTouchMode <= LAST_SCROLL_ZOOM)) {
+ if (!hasFocus() && (null == mWebTextView || !mWebTextView.hasFocus())) {
return;
}
boolean alreadyThere = inEditingMode();
@@ -3365,7 +2988,7 @@
Selection.setSelection(spannable, start, end);
}
} else {
- Rect vBox = contentToView(bounds);
+ Rect vBox = contentToViewRect(bounds);
mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
vBox.height());
mWebTextView.setGravity(nativeFocusCandidateIsRtlText() ?
@@ -3479,11 +3102,9 @@
// Bubble up the key event if
// 1. it is a system key; or
- // 2. the host application wants to handle it; or
- // 3. webview is in scroll-zoom state;
+ // 2. the host application wants to handle it;
if (event.isSystem()
- || mCallbackProxy.uiOverrideKeyEvent(event)
- || (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM)) {
+ || mCallbackProxy.uiOverrideKeyEvent(event)) {
return false;
}
@@ -3630,18 +3251,6 @@
return false;
}
- // special handling in scroll_zoom state
- if (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM) {
- if (KeyEvent.KEYCODE_DPAD_CENTER == keyCode
- && mTouchMode != SCROLL_ZOOM_ANIMATION_IN) {
- setZoomScrollIn();
- mTouchMode = SCROLL_ZOOM_ANIMATION_IN;
- invalidate();
- return true;
- }
- return false;
- }
-
if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
|| keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
if (commitCopy()) {
@@ -3962,11 +3571,8 @@
}
// pass the touch events from UI thread to WebCore thread
- if (mForwardTouchEvents && mTouchMode != SCROLL_ZOOM_OUT
- && mTouchMode != SCROLL_ZOOM_ANIMATION_IN
- && mTouchMode != SCROLL_ZOOM_ANIMATION_OUT
- && (action != MotionEvent.ACTION_MOVE ||
- eventTime - mLastSentTouchTime > TOUCH_SENT_INTERVAL)) {
+ if (mForwardTouchEvents && (action != MotionEvent.ACTION_MOVE
+ || eventTime - mLastSentTouchTime > TOUCH_SENT_INTERVAL)) {
WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData();
ted.mAction = action;
ted.mX = viewToContentX((int) x + mScrollX);
@@ -3980,15 +3586,7 @@
switch (action) {
case MotionEvent.ACTION_DOWN: {
- if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN
- || mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
- // no interaction while animation is in progress
- break;
- } else if (mTouchMode == SCROLL_ZOOM_OUT) {
- mLastScrollX = mZoomScrollX;
- mLastScrollY = mZoomScrollY;
- // If two taps are close, ignore the first tap
- } else if (!mScroller.isFinished()) {
+ if (!mScroller.isFinished()) {
// stop the current scroll animation, but if this is
// the start of a fling, allow it to add to the current
// fling's velocity
@@ -4039,17 +3637,10 @@
break;
}
case MotionEvent.ACTION_MOVE: {
- if (mTouchMode == TOUCH_DONE_MODE
- || mTouchMode == SCROLL_ZOOM_ANIMATION_IN
- || mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
+ if (mTouchMode == TOUCH_DONE_MODE) {
// no dragging during scroll zoom animation
break;
}
- if (mTouchMode == SCROLL_ZOOM_OUT) {
- // while fully zoomed out, move the virtual window
- moveZoomScrollWindow(x, y);
- break;
- }
mVelocityTracker.addMovement(ev);
if (mTouchMode != TOUCH_DRAG_MODE) {
@@ -4097,8 +3688,7 @@
if (settings.supportZoom()
&& settings.getBuiltInZoomControls()
&& !mZoomButtonsController.isVisible()
- && (canZoomScrollOut() ||
- mMinZoomScale < mMaxZoomScale)) {
+ && mMinZoomScale < mMaxZoomScale) {
mZoomButtonsController.setVisible(true);
}
}
@@ -4165,12 +3755,11 @@
if (!getSettings().getBuiltInZoomControls()) {
boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
- boolean showMagnify = canZoomScrollOut();
- if (mZoomControls != null && (showPlusMinus || showMagnify)) {
+ if (mZoomControls != null && showPlusMinus) {
if (mZoomControls.getVisibility() == View.VISIBLE) {
mPrivateHandler.removeCallbacks(mZoomControlRunnable);
} else {
- mZoomControls.show(showPlusMinus, showMagnify);
+ mZoomControls.show(showPlusMinus, false);
}
mPrivateHandler.postDelayed(mZoomControlRunnable,
ZOOM_CONTROLS_TIMEOUT);
@@ -4193,17 +3782,14 @@
doDoubleTap();
break;
case TOUCH_INIT_MODE: // tap
- if (ENABLE_DOUBLETAP_ZOOM) {
- mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
- if (!mPreventDrag) {
- mPrivateHandler.sendMessageDelayed(
- mPrivateHandler.obtainMessage(
- RELEASE_SINGLE_TAP),
- ViewConfiguration.getDoubleTapTimeout());
- }
- break;
+ mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+ if (!mPreventDrag) {
+ mPrivateHandler.sendMessageDelayed(
+ mPrivateHandler.obtainMessage(
+ RELEASE_SINGLE_TAP),
+ ViewConfiguration.getDoubleTapTimeout());
}
- // fall through
+ break;
case TOUCH_SHORTPRESS_START_MODE:
case TOUCH_SHORTPRESS_MODE:
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
@@ -4215,29 +3801,9 @@
commitCopy();
mTouchSelection = false;
break;
- case SCROLL_ZOOM_ANIMATION_IN:
- case SCROLL_ZOOM_ANIMATION_OUT:
- // no action during scroll animation
- break;
- case SCROLL_ZOOM_OUT:
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "ACTION_UP SCROLL_ZOOM_OUT"
- + " eventTime - mLastTouchTime="
- + (eventTime - mLastTouchTime));
- }
- // for now, always zoom back when the drag completes
- if (true || eventTime - mLastTouchTime < TAP_TIMEOUT) {
- // but if we tap, zoom in where we tap
- if (eventTime - mLastTouchTime < TAP_TIMEOUT) {
- zoomScrollTap(x, y);
- }
- // start zooming in back to the original view
- setZoomScrollIn();
- mTouchMode = SCROLL_ZOOM_ANIMATION_IN;
- invalidate();
- }
- break;
case TOUCH_DRAG_MODE:
+ // redraw in high-quality, as we're done dragging
+ invalidate();
// if the user waits a while w/o moving before the
// up, we don't want to do a fling
if (eventTime - mLastTouchTime <= MIN_FLING_TIME) {
@@ -4270,10 +3836,7 @@
mVelocityTracker.recycle();
mVelocityTracker = null;
}
- if (mTouchMode == SCROLL_ZOOM_OUT ||
- mTouchMode == SCROLL_ZOOM_ANIMATION_IN) {
- scrollTo(mZoomScrollX, mZoomScrollY);
- } else if (mTouchMode == TOUCH_DRAG_MODE) {
+ if (mTouchMode == TOUCH_DRAG_MODE) {
WebViewCore.resumeUpdate(mWebViewCore);
}
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
@@ -4372,11 +3935,6 @@
if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent gmail quit");
return false;
}
- // no move if we're still waiting on SWITCH_TO_CLICK timeout
- if (mTouchMode == TOUCH_DOUBLECLICK_MODE) {
- if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent 2 click quit");
- return true;
- }
if (mTrackballDown) {
if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent down quit");
return true; // discard move if trackball is down
@@ -4512,25 +4070,6 @@
int height = mContentHeight - getViewHeight();
if (width < 0) width = 0;
if (height < 0) height = 0;
- if (mTouchMode == SCROLL_ZOOM_OUT) {
- int oldX = mZoomScrollX;
- int oldY = mZoomScrollY;
- int maxWH = Math.max(width, height);
- mZoomScrollX += scaleTrackballX(xRate, maxWH);
- mZoomScrollY += scaleTrackballY(yRate, maxWH);
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "doTrackball SCROLL_ZOOM_OUT"
- + " mZoomScrollX=" + mZoomScrollX
- + " mZoomScrollY=" + mZoomScrollY);
- }
- mZoomScrollX = Math.min(width, Math.max(0, mZoomScrollX));
- mZoomScrollY = Math.min(height, Math.max(0, mZoomScrollY));
- if (oldX != mZoomScrollX || oldY != mZoomScrollY) {
- invalidate();
- }
- mTrackballRemainsX = mTrackballRemainsY = 0;
- return;
- }
ax = Math.abs(mTrackballRemainsX * TRACKBALL_MULTIPLIER);
ay = Math.abs(mTrackballRemainsY * TRACKBALL_MULTIPLIER);
maxA = Math.max(ax, ay);
@@ -4750,14 +4289,6 @@
zoomOut();
}
});
- zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() {
- public void onClick(View v) {
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- mPrivateHandler.postDelayed(mZoomControlRunnable,
- ZOOM_CONTROLS_TIMEOUT);
- zoomScrollOut();
- }
- });
return zoomControls;
}
@@ -4802,7 +4333,7 @@
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
float scale = mActualScale * 0.8f;
- if (scale < (mMinZoomScale + 0.1f) && WebView.ENABLE_DOUBLETAP_ZOOM
+ if (scale < (mMinZoomScale + 0.1f)
&& mWebViewCore.getSettings().getUseWideViewPort()) {
// when zoom out to min scale, switch to overview mode
doDoubleTap();
@@ -4889,6 +4420,9 @@
// In case the soft keyboard has been dismissed, bring it back up.
InputMethodManager.getInstance(getContext()).showSoftInput(mWebTextView,
0);
+ if (nativeFocusNodePointer() != nativeCursorNodePointer()) {
+ nativeMotionUp(x, y, mNavSlop);
+ }
nativeTextInputMotionUp(x, y);
}
@@ -5259,7 +4793,7 @@
setNewZoomScale(mLastScale, false);
setContentScrollTo(restoreState.mScrollX,
restoreState.mScrollY);
- if (ENABLE_DOUBLETAP_ZOOM && useWideViewport
+ if (useWideViewport
&& settings.getLoadWithOverviewMode()) {
if (restoreState.mViewScale == 0
|| (restoreState.mMobileSite
@@ -5286,7 +4820,7 @@
Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
b.left+","+b.top+","+b.right+","+b.bottom+"}");
}
- invalidate(contentToView(draw.mInvalRegion.getBounds()));
+ invalidateContentRect(draw.mInvalRegion.getBounds());
if (mPictureListener != null) {
mPictureListener.onNewPicture(WebView.this, capturePicture());
}
@@ -5745,7 +5279,7 @@
// FIXME the divisor should be retrieved from somewhere
// the closest thing today is hard-coded into ScrollView.java
// (from ScrollView.java, line 363) int maxJump = height/2;
- return viewToContentY(height);
+ return Math.round(height * mInvActualScale);
}
/**
@@ -5785,7 +5319,7 @@
}
Rect contentCursorRingBounds = nativeGetCursorRingBounds();
if (contentCursorRingBounds.isEmpty()) return keyHandled;
- Rect viewCursorRingBounds = contentToView(contentCursorRingBounds);
+ Rect viewCursorRingBounds = contentToViewRect(contentCursorRingBounds);
Rect visRect = new Rect();
calcOurVisibleRect(visRect);
Rect outset = new Rect(visRect);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 26d9343..5f2d65e 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -37,7 +37,6 @@
import java.util.ArrayList;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import junit.framework.Assert;
@@ -838,9 +837,11 @@
case DESTROY:
// Time to take down the world. Cancel all pending
// loads and destroy the native view and frame.
- mBrowserFrame.destroy();
- mBrowserFrame = null;
- mNativeClass = 0;
+ synchronized (WebViewCore.this) {
+ mBrowserFrame.destroy();
+ mBrowserFrame = null;
+ mNativeClass = 0;
+ }
break;
case UPDATE_FRAME_CACHE_IF_LOADING:
@@ -1528,9 +1529,6 @@
// Used to suspend drawing.
private boolean mDrawIsPaused;
- // Used to end scale+scroll mode, accessed by both threads
- boolean mEndScaleZoom = false;
-
// mRestoreState is set in didFirstLayout(), and reset in the next
// webkitDraw after passing it to the UI thread.
private RestoreState mRestoreState = null;
@@ -1571,7 +1569,7 @@
// Send the native view size that was used during the most recent
// layout.
draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
- if (WebView.ENABLE_DOUBLETAP_ZOOM && mSettings.getUseWideViewPort()) {
+ if (mSettings.getUseWideViewPort()) {
draw.mMinPrefWidth = Math.max(
mViewportWidth == -1 ? DEFAULT_VIEWPORT_WIDTH
: (mViewportWidth == 0 ? mCurrentViewWidth
@@ -1627,11 +1625,11 @@
}
}
- /* package */ boolean pictureReady() {
+ /* package */ synchronized boolean pictureReady() {
return nativePictureReady();
}
- /*package*/ Picture copyContentPicture() {
+ /*package*/ synchronized Picture copyContentPicture() {
Picture result = new Picture();
nativeCopyContentToPicture(result);
return result;
@@ -1977,7 +1975,7 @@
// called by JNI
private void restoreScreenWidthScale(int scale) {
- if (!WebView.ENABLE_DOUBLETAP_ZOOM || !mSettings.getUseWideViewPort()) {
+ if (!mSettings.getUseWideViewPort()) {
return;
}
diff --git a/core/java/android/widget/FasttrackBadgeWidget.java b/core/java/android/widget/FasttrackBadgeWidget.java
new file mode 100644
index 0000000..22ca5fd
--- /dev/null
+++ b/core/java/android/widget/FasttrackBadgeWidget.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2009 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.widget;
+
+import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+
+/**
+ * Widget used to show an image with the standard fasttrack badge
+ * and on-click behavior.
+ *
+ * @hide
+ */
+public class FasttrackBadgeWidget extends ImageView implements OnClickListener {
+
+ private Uri mContactUri;
+ private String mContactEmail;
+ private String mContactPhone;
+ private int mMode;
+ private QueryHandler mQueryHandler;
+
+ protected String[] mExcludeMimes = null;
+
+ static final private int TOKEN_EMAIL_LOOKUP = 0;
+ static final private int TOKEN_PHONE_LOOKUP = 1;
+ static final private int TOKEN_EMAIL_LOOKUP_AND_TRIGGER = 2;
+ static final private int TOKEN_PHONE_LOOKUP_AND_TRIGGER = 3;
+
+ static final String[] EMAIL_LOOKUP_PROJECTION = new String[] {
+ RawContacts.CONTACT_ID,
+ Contacts.LOOKUP_KEY,
+ };
+ static int EMAIL_ID_COLUMN_INDEX = 0;
+ static int EMAIL_LOOKUP_STRING_COLUMN_INDEX = 1;
+
+ static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
+ PhoneLookup._ID,
+ PhoneLookup.LOOKUP_KEY,
+ };
+ static int PHONE_ID_COLUMN_INDEX = 0;
+ static int PHONE_LOOKUP_STRING_COLUMN_INDEX = 1;
+
+
+
+ public FasttrackBadgeWidget(Context context) {
+ this(context, null);
+ }
+
+ public FasttrackBadgeWidget(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FasttrackBadgeWidget(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ TypedArray a =
+ context.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.FasttrackBadgeWidget, defStyle, 0);
+
+ mMode = a.getInt(com.android.internal.R.styleable.FasttrackBadgeWidget_fasttrackWindowSize,
+ Intents.MODE_MEDIUM);
+
+ a.recycle();
+
+ init();
+ }
+
+ private void init() {
+ mQueryHandler = new QueryHandler(mContext.getContentResolver());
+ setOnClickListener(this);
+ }
+
+ /**
+ * Assign the contact uri that this fasttrack badge should be associated with.
+ * Note that this is only used for displaying the fasttrack window and won't
+ * bind the contact's photo for you.
+ *
+ * @param conatctUri Either a {Contacts.CONTENT_URI} or {Contacts.CONTENT_LOOKUP_URI}
+ * style URI.
+ */
+ public void assignContactUri(Uri contactUri) {
+ mContactUri = contactUri;
+ }
+
+ /**
+ * Assign a contact based on an email address. This should only be used when
+ * the contact's URI is not available, as an extra query will have to be
+ * performed to lookup the URI based on the email.
+ *
+ * @param emailAddress The email address of the contact.
+ * @param lazyLookup If this is true, the lookup query will not be performed
+ * until this view is clicked.
+ */
+ public void assignContactFromEmail(String emailAddress, boolean lazyLookup) {
+ mContactEmail = emailAddress;
+ if (!lazyLookup) {
+ mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, null,
+ Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
+ EMAIL_LOOKUP_PROJECTION, null, null, null);
+ }
+ }
+
+ /**
+ * Assign a contact based on a phone number. This should only be used when
+ * the contact's URI is not available, as an extra query will have to be
+ * performed to lookup the URI based on the phone number.
+ *
+ * @param phoneNumber The phone number of the contact.
+ * @param lazyLookup If this is true, the lookup query will not be performed
+ * until this view is clicked.
+ */
+ public void assignContactFromPhone(String phoneNumber, boolean lazyLookup) {
+ mContactPhone = phoneNumber;
+ if (!lazyLookup) {
+ mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, null,
+ Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
+ PHONE_LOOKUP_PROJECTION, null, null, null);
+ }
+ }
+
+ /**
+ * Set the fasttrack window mode. Options are {@link Intents.MODE_SMALL},
+ * {@link Intents.MODE_MEDIUM}, {@link Intents.MODE_LARGE}.
+ * @param size
+ */
+ public void setMode(int size) {
+ mMode = size;
+ }
+
+ public void onClick(View v) {
+ final Rect target = getTargetRect(v);
+
+ if (mContactUri != null) {
+ trigger(mContactUri, target);
+ } else if (mContactEmail != null) {
+ mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP_AND_TRIGGER, target,
+ Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
+ EMAIL_LOOKUP_PROJECTION, null, null, null);
+ } else if (mContactPhone != null) {
+ mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP_AND_TRIGGER, target,
+ Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
+ PHONE_LOOKUP_PROJECTION, null, null, null);
+ } else {
+ // If a contact hasn't been assigned, don't react to click.
+ return;
+ }
+ }
+
+ /**
+ * Set a list of specific MIME-types to exclude and not display. For
+ * example, this can be used to hide the {@link Contacts#CONTENT_ITEM_TYPE}
+ * profile icon.
+ */
+ public void setExcludeMimes(String[] excludeMimes) {
+ mExcludeMimes = excludeMimes;
+ }
+
+ private void trigger(Uri contactUri, Rect target) {
+ Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, contactUri);
+ intent.putExtra(Intents.EXTRA_TARGET_RECT, target);
+ intent.putExtra(Intents.EXTRA_MODE, mMode);
+ mContext.startActivity(intent);
+ }
+
+ private Rect getTargetRect(View anchor) {
+ final int[] location = new int[2];
+ anchor.getLocationOnScreen(location);
+
+ final Rect rect = new Rect();
+ rect.left = location[0];
+ rect.top = location[1];
+ rect.right = rect.left + anchor.getWidth();
+ rect.bottom = rect.top + anchor.getHeight();
+ return rect;
+ }
+
+ private class QueryHandler extends AsyncQueryHandler {
+
+ public QueryHandler(ContentResolver cr) {
+ super(cr);
+ }
+
+ @Override
+ protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ Uri contactUri = null;
+ boolean trigger = false;
+
+ try{
+ switch(token) {
+ case TOKEN_PHONE_LOOKUP_AND_TRIGGER:
+ trigger = true;
+ case TOKEN_PHONE_LOOKUP: {
+ if (cursor != null && cursor.moveToFirst()) {
+ long contactId = cursor.getLong(PHONE_ID_COLUMN_INDEX);
+ String lookupKey = cursor.getString(PHONE_LOOKUP_STRING_COLUMN_INDEX);
+ contactUri = Contacts.getLookupUri(contactId, lookupKey);
+ }
+ break;
+ }
+ case TOKEN_EMAIL_LOOKUP_AND_TRIGGER:
+ trigger = true;
+ case TOKEN_EMAIL_LOOKUP: {
+ if (cursor != null && cursor.moveToFirst()) {
+ long contactId = cursor.getLong(EMAIL_ID_COLUMN_INDEX);
+ String lookupKey = cursor.getString(EMAIL_LOOKUP_STRING_COLUMN_INDEX);
+ contactUri = Contacts.getLookupUri(contactId, lookupKey);
+ }
+ }
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+
+ if (contactUri != null) {
+ mContactUri = contactUri;
+ if (trigger && cookie != null) {
+ trigger(contactUri, (Rect) cookie);
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 9ec8347..33e83c3 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1148,9 +1148,12 @@
if (sel != null) {
positionSelector(sel);
mSelectedTop = sel.getTop();
+ } else if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) {
+ View child = getChildAt(mMotionPosition - mFirstPosition);
+ positionSelector(child);
} else {
- mSelectedTop = 0;
- mSelectorRect.setEmpty();
+ mSelectedTop = 0;
+ mSelectorRect.setEmpty();
}
mLayoutMode = LAYOUT_NORMAL;
@@ -1231,8 +1234,12 @@
private void setupChild(View child, int position, int y, boolean flow, int childrenLeft,
boolean selected, boolean recycled, int where) {
boolean isSelected = selected && shouldShowSelector();
-
final boolean updateChildSelected = isSelected != child.isSelected();
+ final int mode = mTouchMode;
+ final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
+ mMotionPosition == position;
+ final boolean updateChildPressed = isPressed != child.isPressed();
+
boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
// Respect layout params that are already in the view. Otherwise make
@@ -1257,6 +1264,10 @@
}
}
+ if (updateChildPressed) {
+ child.setPressed(isPressed);
+ }
+
if (needToMeasure) {
int childHeightSpec = ViewGroup.getChildMeasureSpec(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 6316864..41c9267 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1542,37 +1542,42 @@
recycleBin.scrapActiveViews();
if (sel != null) {
- // the current selected item should get focus if items
- // are focusable
- if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) {
- final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild &&
- focusLayoutRestoreView.requestFocus()) || sel.requestFocus();
- if (!focusWasTaken) {
- // selected item didn't take focus, fine, but still want
- // to make sure something else outside of the selected view
- // has focus
- final View focused = getFocusedChild();
- if (focused != null) {
- focused.clearFocus();
- }
- positionSelector(sel);
- } else {
- sel.setSelected(false);
- mSelectorRect.setEmpty();
- }
- } else {
- positionSelector(sel);
- }
- mSelectedTop = sel.getTop();
+ // the current selected item should get focus if items
+ // are focusable
+ if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) {
+ final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild &&
+ focusLayoutRestoreView.requestFocus()) || sel.requestFocus();
+ if (!focusWasTaken) {
+ // selected item didn't take focus, fine, but still want
+ // to make sure something else outside of the selected view
+ // has focus
+ final View focused = getFocusedChild();
+ if (focused != null) {
+ focused.clearFocus();
+ }
+ positionSelector(sel);
+ } else {
+ sel.setSelected(false);
+ mSelectorRect.setEmpty();
+ }
+ } else {
+ positionSelector(sel);
+ }
+ mSelectedTop = sel.getTop();
} else {
- mSelectedTop = 0;
- mSelectorRect.setEmpty();
+ if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) {
+ View child = getChildAt(mMotionPosition - mFirstPosition);
+ positionSelector(child);
+ } else {
+ mSelectedTop = 0;
+ mSelectorRect.setEmpty();
+ }
- // even if there is not selected position, we may need to restore
- // focus (i.e. something focusable in touch mode)
- if (hasFocus() && focusLayoutRestoreView != null) {
- focusLayoutRestoreView.requestFocus();
- }
+ // even if there is not selected position, we may need to restore
+ // focus (i.e. something focusable in touch mode)
+ if (hasFocus() && focusLayoutRestoreView != null) {
+ focusLayoutRestoreView.requestFocus();
+ }
}
// tell focus view we are done mucking with it, if it is still in
@@ -1686,6 +1691,10 @@
boolean selected, boolean recycled) {
final boolean isSelected = selected && shouldShowSelector();
final boolean updateChildSelected = isSelected != child.isSelected();
+ final int mode = mTouchMode;
+ final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
+ mMotionPosition == position;
+ final boolean updateChildPressed = isPressed != child.isPressed();
final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
// Respect layout params that are already in the view. Otherwise make some up...
@@ -1711,6 +1720,10 @@
child.setSelected(isSelected);
}
+ if (updateChildPressed) {
+ child.setPressed(isPressed);
+ }
+
if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
if (child instanceof Checkable) {
((Checkable) child).setChecked(mCheckStates.get(position));
diff --git a/core/res/res/drawable/fasttrack_badge_middle.xml b/core/res/res/drawable/fasttrack_badge_middle_large.xml
similarity index 85%
rename from core/res/res/drawable/fasttrack_badge_middle.xml
rename to core/res/res/drawable/fasttrack_badge_middle_large.xml
index 6df230a..dd591bd 100644
--- a/core/res/res/drawable/fasttrack_badge_middle.xml
+++ b/core/res/res/drawable/fasttrack_badge_middle_large.xml
@@ -19,10 +19,10 @@
android:state_focused="false"
android:state_selected="false"
android:state_pressed="false"
- android:drawable="@drawable/fasttrack_badge_middle_normal" />
+ android:drawable="@drawable/fasttrack_badge_middle_large_normal" />
<item
android:state_pressed="true"
- android:drawable="@drawable/fasttrack_badge_middle_pressed" />
+ android:drawable="@drawable/fasttrack_badge_middle_large_pressed" />
</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/fasttrack_badge_middle_large_normal.9.png b/core/res/res/drawable/fasttrack_badge_middle_large_normal.9.png
new file mode 100644
index 0000000..ca275cd
--- /dev/null
+++ b/core/res/res/drawable/fasttrack_badge_middle_large_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_badge_middle_large_pressed.9.png b/core/res/res/drawable/fasttrack_badge_middle_large_pressed.9.png
new file mode 100644
index 0000000..b69ccbd
--- /dev/null
+++ b/core/res/res/drawable/fasttrack_badge_middle_large_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_badge_middle_normal.9.png b/core/res/res/drawable/fasttrack_badge_middle_normal.9.png
deleted file mode 100644
index 07df063..0000000
--- a/core/res/res/drawable/fasttrack_badge_middle_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_badge_middle_pressed.9.png b/core/res/res/drawable/fasttrack_badge_middle_pressed.9.png
deleted file mode 100644
index ded95f6..0000000
--- a/core/res/res/drawable/fasttrack_badge_middle_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml
index ba91e00..8d7e470 100644
--- a/core/res/res/layout/contact_header.xml
+++ b/core/res/res/layout/contact_header.xml
@@ -24,12 +24,12 @@
android:gravity="center_vertical">
<ImageView android:id="@+id/photo"
- android:layout_width="48dip"
- android:layout_height="52dip"
+ android:layout_width="56dip"
+ android:layout_height="62dip"
android:layout_marginRight="10dip"
android:layout_marginLeft="10dip"
android:scaleType="fitCenter"
- android:background="@drawable/fasttrack_badge_middle"/>
+ android:background="@drawable/fasttrack_badge_middle_large"/>
<LinearLayout
android:layout_width="0dip"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d1cb0bd..a1a179b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -396,6 +396,14 @@
<attr name="spinnerItemStyle" format="reference" />
<!-- Default MapView style. -->
<attr name="mapViewStyle" format="reference" />
+ <!-- Dark Fasttrack badge style. -->
+ <attr name="fasttrackBadgeWidgetStyle" format="reference" />
+ <!-- Dark Fasttrack badge style with small fasttrack window. -->
+ <attr name="fasttrackBadgeWidgetStyleWindowSmall" format="reference" />
+ <!-- Dark Fasttrack badge style with medium fasttrack window. -->
+ <attr name="fasttrackBadgeWidgetStyleWindowMedium" format="reference" />
+ <!-- Dark Fasttrack badge style with large fasttrack window. -->
+ <attr name="fasttrackBadgeWidgetStyleWindowLarge" format="reference" />
<!-- =================== -->
<!-- Preference styles -->
@@ -2197,6 +2205,14 @@
<attr name="orientation" />
</declare-styleable>
+ <declare-styleable name="FasttrackBadgeWidget">
+ <attr name="fasttrackWindowSize">
+ <enum name="modeSmall" value="1" />
+ <enum name="modeMedium" value="2" />
+ <enum name="modeLarge" value="3" />
+ </attr>
+ </declare-styleable>
+
<!-- ======================================= -->
<!-- Widget package parent layout attributes -->
<!-- ======================================= -->
@@ -2843,9 +2859,7 @@
is also used as an icon to the left of the search box and you cannot modify this
behavior, so including the icon attribute is unecessary and this may be
deprecated in the future.
- <i>Optional attribute.</i>
- {@deprecated This will create a non-standard UI appearance, because the search bar UI
- now puts the activity or application icon beside the search box.} -->
+ <i>Optional attribute.</i> -->
<attr name="icon" />
<!-- This is the user-displayed name of the searchable activity. <i>Required
attribute.</i> -->
@@ -2870,10 +2884,7 @@
<flag name="showSearchLabelAsBadge" value="0x04" />
<!-- If set, this flag enables the display of the search target (icon) within the
search bar. (Note, overrides showSearchLabel) If neither bad mode is selected,
- no badge will be shown.
- {@deprecated This will create a non-standard UI appearance, because the search bar UI
- now puts the activity or application icon beside the search box.}
- -->
+ no badge will be shown.-->
<flag name="showSearchIconAsBadge" value="0x08" />
<!-- If set, this flag causes the suggestion column SUGGEST_COLUMN_INTENT_DATA to
be considered as the text for suggestion query rewriting. This should only
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0902c21..69ddd63 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -234,7 +234,7 @@
supply an auth token without prompting the user to re-enter the
password. This is the text that will scroll through the
notification bar (will be seen by the user as he uses another application). -->
- <string name="notification_title">Sign-in error</string>
+ <string name="notification_title">Sign-in error for <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g></string>
<!-- Sync notifications --> <skip />
<!-- A notification is shown when there is a sync error. This is the text that will scroll through the notification bar (will be seen by the user as he uses another application). -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index a2ceb8f..fae612c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -517,6 +517,26 @@
<item name="android:shadowRadius">2.75</item>
</style>
+ <style name="Widget.FasttrackBadgeWidget">
+ <item name="android:layout_width">48dip</item>
+ <item name="android:layout_height">52dip</item>
+ <item name="android:background">@android:drawable/fasttrack_badge_dark</item>
+ <item name="android:clickable">true</item>
+ <item name="android:scaleType">fitCenter</item>
+ </style>
+
+ <style name="Widget.FasttrackBadgeWidget.WindowSmall">
+ <item name="android:fasttrackWindowSize">modeSmall</item>
+ </style>
+
+ <style name="Widget.FasttrackBadgeWidget.WindowMedium">
+ <item name="android:fasttrackWindowSize">modeMedium</item>
+ </style>
+
+ <style name="Widget.FasttrackBadgeWidget.WindowLarge">
+ <item name="android:fasttrackWindowSize">modeLarge</item>
+ </style>
+
<!-- Text Appearances -->
<eat-comment />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 3b9590d..4f76c56 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -176,6 +176,9 @@
<item name="spinnerItemStyle">@android:style/Widget.TextView.SpinnerItem</item>
<item name="dropDownHintAppearance">@android:style/TextAppearance.Widget.DropDownHint</item>
<item name="keyboardViewStyle">@android:style/Widget.KeyboardView</item>
+ <item name="fasttrackBadgeWidgetStyleWindowSmall">@android:style/Widget.FasttrackBadgeWidget.WindowSmall</item>
+ <item name="fasttrackBadgeWidgetStyleWindowMedium">@android:style/Widget.FasttrackBadgeWidget.WindowMedium</item>
+ <item name="fasttrackBadgeWidgetStyleWindowLarge">@android:style/Widget.FasttrackBadgeWidget.WindowLarge</item>
<!-- Preference styles -->
<item name="preferenceScreenStyle">@android:style/Preference.PreferenceScreen</item>
diff --git a/docs/html/guide/topics/resources/available-resources.jd b/docs/html/guide/topics/resources/available-resources.jd
index 0dfc625..f5f1475 100644
--- a/docs/html/guide/topics/resources/available-resources.jd
+++ b/docs/html/guide/topics/resources/available-resources.jd
@@ -908,7 +908,7 @@
</p>
<pre>
<<em>ViewGroupClass</em> xmlns:android="http://schemas.android.com/apk/res/android"
- id="@+id/<em>string_name</em>" (attributes)>
+ android:id="@+id/<em>string_name</em>" (attributes)>
<<em>widget</em> or other nested <em>ViewGroupClass</em>>+
<requestFocus/>(0 or 1 per layout file, assigned to any element)
</<em>ViewGroupClass</em>>
@@ -919,7 +919,7 @@
</dt>
<dd>
<p>The file must have a single root element. This can be a ViewGroup class that contains other elements, or a widget (or custom item) if it's only one object. By default, you can use any (case-sensitive) Android {@link android.widget widget} or {@link android.view.ViewGroup ViewGroup} class name as an element. These elements support attributes that apply to the underlying class, but the naming is not as clear. How to discover what attributes are supported for what tags is discussed below. You should not assume that any nesting is valid (for example you cannot enclose <code><TextView></code> elements inside a <code><ListLayout></code>).</p>
- <p>If a class derives from another class, the XML element inherits all the attributes from the element that it "derives" from. So, for example, <code><EditText></code> is the corresponding XML element for the EditText class. It exposes its own unique attributes (<code>EditText_numeric</code>), as well as all attributes supported by <code><TextView></code> and <code><View></code>. For the <em>id</em> attribute of a tag in XML, you should use a special syntax: "@+id/<em>somestringvalue</em>". The "@+" syntax creates a resource number in the R.id class, if one doesn't exist, or uses it, if it does exist. When declaring an ID value for an XML tag, use this syntax. Example: <code><TextView id="@+id/nameTextbox"/></code>, and refer to it this way in Java: <code>findViewById(R.id.nameTextbox)</code>. All elements support the following values:</p>
+ <p>If a class derives from another class, the XML element inherits all the attributes from the element that it "derives" from. So, for example, <code><EditText></code> is the corresponding XML element for the EditText class. It exposes its own unique attributes (<code>EditText_numeric</code>), as well as all attributes supported by <code><TextView></code> and <code><View></code>. For the <em>id</em> attribute of a tag in XML, you should use a special syntax: "@+id/<em>somestringvalue</em>". The "@+" syntax creates a resource number in the R.id class, if one doesn't exist, or uses it, if it does exist. When declaring an ID value for an XML tag, use this syntax. Example: <code><TextView android:id="@+id/nameTextbox"/></code>, and refer to it this way in Java: <code>findViewById(R.id.nameTextbox)</code>. All elements support the following values:</p>
<ul>
<li>
<em>id</em> - An ID value used to access this element in Java. Typically you will use the syntax @+id/<em>string_name</em> to generate an ID for you in the id.xml file if you haven't created one yourself.
@@ -1007,7 +1007,7 @@
android:paddingBottom="4" // TextView.paddingBottom
android:text="@string/redirect_getter"/> // TextView.text
- <EditText id="@+id/text"
+ <EditText android:id="@+id/text"
android:layout_width="fill_parent" // EditText.LayoutParams.width
android:layout_height="wrap_content" // EditText.LayoutParams.height
android:layout_weight="0" // EditText.LinearLayoutParams.weight
@@ -1015,7 +1015,7 @@
<requestFocus />
</EditText>
- <Button id="@+id/apply"
+ <Button android:id="@+id/apply"
android:layout_width="wrap_content" // Button.LayoutParams.width
android:layout_height="wrap_content" // Button.LayoutParams.height
android:text="@string/apply" /> // TextView.text
@@ -1047,7 +1047,7 @@
<strong>Java implementation file</strong> - The implementation file. The class must extend {@link android.view.View View} or a subclass. See LabelView.java in ApiDemos.
</li>
<li>
- <strong>res/values/attrs.xml</strong> - Defines the XML element, and the attributes that it supports, for clients to use to instantiate your object in their layout XML file. Define your element in a <code><declare-styleable id=<em>your_java_class_name</em>></code>. See res/layout/attrs.xml in ApiDemos.
+ <strong>res/values/attrs.xml</strong> - Defines the XML element, and the attributes that it supports, for clients to use to instantiate your object in their layout XML file. Define your element in a <code><declare-styleable name=<em>your_java_class_name</em>></code>. See res/values/attrs.xml in ApiDemos.
</li>
<li>
<strong>res/layout/<em>your_class</em>.xml</strong> [<em>optional</em>] - An optional XML file to describe the layout of your object. This could also be done in Java. See custom_view_1.xml in ApiDemos.
diff --git a/docs/html/sdk/1.6_r1/index.jd b/docs/html/sdk/1.6_r1/index.jd
index 419649e..8f33949 100644
--- a/docs/html/sdk/1.6_r1/index.jd
+++ b/docs/html/sdk/1.6_r1/index.jd
@@ -5,16 +5,16 @@
sdk.date=September 2009
sdk.win_download=android-sdk-windows-1.6_r1.zip
-sdk.win_bytes=251325064
-sdk.win_checksum=efd6fccd5a6ff6b57585b49393d221d9
+sdk.win_bytes=260529085
+sdk.win_checksum=2bcbacbc7af0363058ca1cac6abad848
sdk.mac_download=android-sdk-mac_x86-1.6_r1.zip
-sdk.mac_bytes=238229779
-sdk.mac_checksum=2be1a1ae5d33272be841c97e8a3a3b1c
+sdk.mac_bytes=247412515
+sdk.mac_checksum=eb13cc79602d492e89103efcf48ac1f6
sdk.linux_download=android-sdk-linux_x86-1.6_r1.tgz
-sdk.linux_bytes=229032773
-sdk.linux_checksum=02ff0d0e38d4f464108a5a7f7567b207
+sdk.linux_bytes=238224860
+sdk.linux_checksum=b4bf0e610ff6db2fb6fb09c49cba1e79
adt.zip_download=ADT-0.9.3.zip
adt.zip_version=0.9.3
diff --git a/docs/html/sdk/android-1.6-highlights.jd b/docs/html/sdk/android-1.6-highlights.jd
index 74dcd9f..b4a97d7 100644
--- a/docs/html/sdk/android-1.6-highlights.jd
+++ b/docs/html/sdk/android-1.6-highlights.jd
@@ -113,7 +113,7 @@
<h3 id="A11y">Accessibility</h3>
<p>Users will be able to download new accessibility services built
-on the new Accessibility framework and enable them in Settings.</p>
+on the new accessibility framework and enable them in Settings.</p>
diff --git a/graphics/java/android/graphics/BlurMaskFilter.java b/graphics/java/android/graphics/BlurMaskFilter.java
index dbf57ac..5eafe76 100644
--- a/graphics/java/android/graphics/BlurMaskFilter.java
+++ b/graphics/java/android/graphics/BlurMaskFilter.java
@@ -16,13 +16,19 @@
package android.graphics;
+/**
+ * This takes a mask, and blurs its edge by the specified radius. Whether or
+ * or not to include the original mask, and whether the blur goes outside,
+ * inside, or straddles, the original mask's border, is controlled by the
+ * Blur enum.
+ */
public class BlurMaskFilter extends MaskFilter {
public enum Blur {
- NORMAL(0), //!< fuzzy inside and outside
- SOLID(1), //!< solid inside, fuzzy outside
- OUTER(2), //!< nothing inside, fuzzy outside
- INNER(3); //!< fuzzy inside, nothing outside
+ NORMAL(0), //!< blur inside and outside of the original border
+ SOLID(1), //!< include the original mask, blur outside
+ OUTER(2), //!< just blur outside the original border
+ INNER(3); //!< just blur inside the original border
Blur(int value) {
native_int = value;
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 7749ad34..30c81ab 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -113,6 +113,10 @@
mRS.nAllocationSubDataFromObject(mID, mType, 0, o);
}
+ public void read(Object o) {
+ mRS.nAllocationSubReadFromObject(mID, mType, 0, o);
+ }
+
public void subData(int offset, Object o) {
mRS.nAllocationSubDataFromObject(mID, mType, offset, o);
}
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 6f5b67e..89db4fa 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -106,6 +106,7 @@
native void nAllocationRead(int id, int[] d);
native void nAllocationRead(int id, float[] d);
native void nAllocationSubDataFromObject(int id, Type t, int offset, Object o);
+ native void nAllocationSubReadFromObject(int id, Type t, int offset, Object o);
native void nTriangleMeshBegin(int vertex, int index);
native void nTriangleMeshAddVertex_XY (float x, float y);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index a94ccb1..90b5958 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -253,10 +253,39 @@
return ((uint8_t *)buffer) + 4;
}
+static void * SF_SaveInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+ LOGE("Save Int");
+ _env->SetIntField(_obj, _field, ((int32_t *)buffer)[0]);
+ return ((uint8_t *)buffer) + 4;
+}
+
+static void * SF_SaveShort(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+ LOGE("Save Short");
+ _env->SetShortField(_obj, _field, ((int16_t *)buffer)[0]);
+ return ((uint8_t *)buffer) + 2;
+}
+
+static void * SF_SaveByte(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+ LOGE("Save Byte");
+ _env->SetByteField(_obj, _field, ((int8_t *)buffer)[0]);
+ return ((uint8_t *)buffer) + 1;
+}
+
+static void * SF_SaveFloat(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+ LOGE("Save Float");
+ _env->SetFloatField(_obj, _field, ((float *)buffer)[0]);
+ return ((uint8_t *)buffer) + 4;
+}
+
struct TypeFieldCache {
jfieldID field;
int bits;
void * (*ptr)(JNIEnv *, jobject, jfieldID, void *buffer);
+ void * (*readPtr)(JNIEnv *, jobject, jfieldID, void *buffer);
};
struct TypeCache {
@@ -296,13 +325,23 @@
switch(fType[ct]) {
case RS_TYPE_FLOAT:
tfc[ct].ptr = SF_LoadFloat;
+ tfc[ct].readPtr = SF_SaveFloat;
break;
case RS_TYPE_UNSIGNED:
case RS_TYPE_SIGNED:
switch(tfc[ct].bits) {
- case 32: tfc[ct].ptr = SF_LoadInt; break;
- case 16: tfc[ct].ptr = SF_LoadShort; break;
- case 8: tfc[ct].ptr = SF_LoadByte; break;
+ case 32:
+ tfc[ct].ptr = SF_LoadInt;
+ tfc[ct].readPtr = SF_SaveInt;
+ break;
+ case 16:
+ tfc[ct].ptr = SF_LoadShort;
+ tfc[ct].readPtr = SF_SaveShort;
+ break;
+ case 8:
+ tfc[ct].ptr = SF_LoadByte;
+ tfc[ct].readPtr = SF_SaveByte;
+ break;
}
break;
}
@@ -545,7 +584,30 @@
buf = tfc->ptr(_env, _o, tfc->field, buf);
}
rsAllocation1DSubData(con, (RsAllocation)alloc, offset, 1, bufAlloc, tc->size);
- const uint32_t * tmp = (const uint32_t *)bufAlloc;
+ free(bufAlloc);
+}
+
+static void
+nAllocationSubReadFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jint offset, jobject _o)
+{
+ RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+ LOG_API("nAllocationReadFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
+
+ assert(offset == 0);
+
+ const TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
+
+ void * bufAlloc = malloc(tc->size);
+ void * buf = bufAlloc;
+ rsAllocationRead(con, (RsAllocation)alloc, bufAlloc);
+
+ LOGE("size %i, ", tc->size);
+
+ for (int ct=0; ct < tc->fieldCount; ct++) {
+ const TypeFieldCache *tfc = &tc->fields[ct];
+ LOGE("ct=%i, buf=%p", ct, buf);
+ buf = tfc->readPtr(_env, _o, tfc->field, buf);
+ }
free(bufAlloc);
}
@@ -1270,6 +1332,7 @@
{"nAllocationRead", "(I[I)V", (void*)nAllocationRead_i },
{"nAllocationRead", "(I[F)V", (void*)nAllocationRead_f },
{"nAllocationSubDataFromObject", "(ILandroid/renderscript/Type;ILjava/lang/Object;)V", (void*)nAllocationSubDataFromObject },
+{"nAllocationSubReadFromObject", "(ILandroid/renderscript/Type;ILjava/lang/Object;)V", (void*)nAllocationSubReadFromObject },
{"nTriangleMeshBegin", "(II)V", (void*)nTriangleMeshBegin },
{"nTriangleMeshAddVertex_XY", "(FF)V", (void*)nTriangleMeshAddVertex_XY },
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 0014d5c..10e0197 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -25,6 +25,8 @@
#include <OMX_Core.h>
#include <OMX_Video.h>
+#include "jni.h"
+
namespace android {
class IMemory;
@@ -102,15 +104,22 @@
size_t encodedWidth, size_t encodedHeight,
size_t displayWidth, size_t displayHeight) = 0;
- // Note: This method is _not_ virtual, it exists as a wrapper around
+ // Note: These methods are _not_ virtual, it exists as a wrapper around
// the virtual "createRenderer" method above facilitating extraction
- // of the ISurface from a regular Surface.
+ // of the ISurface from a regular Surface or a java Surface object.
sp<IOMXRenderer> createRenderer(
const sp<Surface> &surface,
const char *componentName,
OMX_COLOR_FORMATTYPE colorFormat,
size_t encodedWidth, size_t encodedHeight,
size_t displayWidth, size_t displayHeight);
+
+ sp<IOMXRenderer> createRendererFromJavaSurface(
+ JNIEnv *env, jobject javaSurface,
+ const char *componentName,
+ OMX_COLOR_FORMATTYPE colorFormat,
+ size_t encodedWidth, size_t encodedHeight,
+ size_t displayWidth, size_t displayHeight);
};
struct omx_message {
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 9d442c3..7c01687 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -37,6 +37,7 @@
endif
LOCAL_C_INCLUDES := \
+ $(JNI_H_INCLUDE) \
$(call include-path-for, graphics corecg) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 10bebd0..0cec7bb 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -45,6 +45,31 @@
displayWidth, displayHeight);
}
+sp<IOMXRenderer> IOMX::createRendererFromJavaSurface(
+ JNIEnv *env, jobject javaSurface,
+ const char *componentName,
+ OMX_COLOR_FORMATTYPE colorFormat,
+ size_t encodedWidth, size_t encodedHeight,
+ size_t displayWidth, size_t displayHeight) {
+ jclass surfaceClass = env->FindClass("android/view/Surface");
+ if (surfaceClass == NULL) {
+ LOGE("Can't find android/view/Surface");
+ return NULL;
+ }
+
+ jfieldID surfaceID = env->GetFieldID(surfaceClass, "mSurface", "I");
+ if (surfaceID == NULL) {
+ LOGE("Can't find Surface.mSurface");
+ return NULL;
+ }
+
+ sp<Surface> surface = (Surface *)env->GetIntField(javaSurface, surfaceID);
+
+ return createRenderer(
+ surface, componentName, colorFormat, encodedWidth,
+ encodedHeight, displayWidth, displayHeight);
+}
+
class BpOMX : public BpInterface<IOMX> {
public:
BpOMX(const sp<IBinder> &impl)
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 93b7a3a..f21eb73 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -47,6 +47,7 @@
endif
LOCAL_C_INCLUDES := external/tremor/Tremor \
+ $(JNI_H_INCLUDE) \
$(call include-path-for, graphics corecg) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
$(TOP)/frameworks/base/media/libstagefright/omx
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 79a32b5..3c343a3 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -38,6 +38,7 @@
endif
LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
$(TOP)/external/opencore/android
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 77e42be..4cadccd 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -7,6 +7,7 @@
LOCAL_CFLAGS := $(PV_CFLAGS_MINUS_VISIBILITY)
LOCAL_C_INCLUDES += $(TOP)/hardware/ti/omap3/liboverlay
+LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)
LOCAL_SRC_FILES:= \
OMX.cpp \
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
new file mode 100644
index 0000000..0401390
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
@@ -0,0 +1,84 @@
+package com.android.mediaframeworktest;
+
+import android.media.MediaRecorder;
+import android.os.SystemProperties;
+import java.util.HashMap;
+
+public class MediaProfileReader {
+
+ public static final HashMap<String, Integer>
+ OUTPUT_FORMAT_TABLE = new HashMap<String, Integer>();
+ public static String MEDIA_ENC_VID = "ro.media.enc.vid.";
+ public static String MEDIA_AUD_VID = "ro.media.enc.aud.";
+ public static String[] VIDEO_ENCODER_PROPERTY = {".width", ".height", ".bps", ".fps",};
+ public static String[] AUDIO_ENCODER_PROPERTY = {".bps", ".hz", ".ch",};
+
+ public static String getVideoCodecProperty() {
+ String s;
+ s = SystemProperties.get("ro.media.enc.vid.codec");
+ return s;
+ }
+
+ public static String getAudioCodecProperty() {
+ String s;
+ s = SystemProperties.get("ro.media.enc.aud.codec");
+ return s;
+ }
+
+ public static String getDeviceType() {
+ // push all the property into one big table
+ String s;
+ s = SystemProperties.get("ro.product.name");
+ return s;
+ }
+
+ public static void createVideoProfileTable() {
+ // push all the property into one big table
+ String encoderType = getVideoCodecProperty();
+ String encoder[] = encoderType.split(",");
+ for (int i = 0; i < encoder.length; i++) {
+ for (int j = 0; j < VIDEO_ENCODER_PROPERTY.length; j++) {
+ String propertyName = MEDIA_ENC_VID + encoder[i] + VIDEO_ENCODER_PROPERTY[j];
+ String prop = SystemProperties.get(propertyName);
+ //push to the table
+ String propRange[] = prop.split(",");
+ OUTPUT_FORMAT_TABLE.put((encoder[i] + VIDEO_ENCODER_PROPERTY[j] + "_low"),
+ Integer.parseInt(propRange[0]));
+ OUTPUT_FORMAT_TABLE.put((encoder[i] + VIDEO_ENCODER_PROPERTY[j] + "_high"),
+ Integer.parseInt(propRange[1]));
+ }
+
+ }
+ }
+
+ public static void createAudioProfileTable() {
+ // push all the property into one big table
+ String audioType = getAudioCodecProperty();
+ String encoder[] = audioType.split(",");
+ for (int i = 0; i < encoder.length; i++) {
+ for (int j = 0; j < AUDIO_ENCODER_PROPERTY.length; j++) {
+ String propertyName = MEDIA_AUD_VID + encoder[i] + AUDIO_ENCODER_PROPERTY[j];
+ String prop = SystemProperties.get(propertyName);
+ //push to the table
+ String propRange[] = prop.split(",");
+ OUTPUT_FORMAT_TABLE.put((encoder[i] + AUDIO_ENCODER_PROPERTY[j] + "_low"),
+ Integer.parseInt(propRange[0]));
+ OUTPUT_FORMAT_TABLE.put((encoder[i] + AUDIO_ENCODER_PROPERTY[j] + "_high"),
+ Integer.parseInt(propRange[1]));
+ }
+
+ }
+ }
+
+ public static void createEncoderTable(){
+ OUTPUT_FORMAT_TABLE.put("h263", MediaRecorder.VideoEncoder.H263);
+ OUTPUT_FORMAT_TABLE.put("h264", MediaRecorder.VideoEncoder.H264);
+ OUTPUT_FORMAT_TABLE.put("m4v", MediaRecorder.VideoEncoder.MPEG_4_SP);
+ OUTPUT_FORMAT_TABLE.put("amrnb", MediaRecorder.AudioEncoder.AMR_NB);
+ OUTPUT_FORMAT_TABLE.put("amrwb", MediaRecorder.AudioEncoder.AMR_WB);
+ OUTPUT_FORMAT_TABLE.put("aac", MediaRecorder.AudioEncoder.AAC);
+ OUTPUT_FORMAT_TABLE.put("aacplus", MediaRecorder.AudioEncoder.AAC_PLUS);
+ OUTPUT_FORMAT_TABLE.put("eaacplus",
+ MediaRecorder.AudioEncoder.EAAC_PLUS);
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index ef0a3b1..39846c6 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -29,7 +29,7 @@
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
-
+import com.android.mediaframeworktest.MediaProfileReader;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
@@ -46,6 +46,9 @@
private SurfaceHolder mSurfaceHolder = null;
private MediaRecorder mRecorder;
+
+ private int MIN_VIDEO_FPS = 5;
+
Context mContext;
Camera mCamera;
@@ -96,7 +99,70 @@
}
}
-
+ private boolean recordVideoWithPara(String encoder, String audio, String quality){
+ boolean recordSuccess = false;
+ int videoEncoder = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder);
+ int audioEncoder = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio);
+ int videoWidth = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".width_" + quality);
+ int videoHeight =
+ MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".height_" + quality);
+ int videoFps = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".fps_" + quality);
+ int videoBitrate = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".bps_" + quality);
+ int audioBitrate = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".bps_" + quality);
+ int audioChannels = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".ch_" + quality);
+ int audioSamplingRate =
+ MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".hz_" + quality);
+
+ if (videoFps < MIN_VIDEO_FPS) {
+ videoFps = MIN_VIDEO_FPS;
+ }
+ mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ String filename = ("/sdcard/" + encoder + "_" + audio + "_" + quality + ".3gp");
+ try {
+ Log.v(TAG, "video encoder :" + videoEncoder);
+ Log.v(TAG, "audio encoder :" + audioEncoder);
+ Log.v(TAG, "quality : " + quality);
+ Log.v(TAG, "encoder : " + encoder);
+ Log.v(TAG, "audio : " + audio);
+ Log.v(TAG, "videoWidth : " + videoWidth);
+ Log.v(TAG, "videoHeight : " + videoHeight);
+ Log.v(TAG, "videoFPS : " + videoFps);
+ Log.v(TAG, "videobitrate : " + videoBitrate);
+ Log.v(TAG, "audioBitrate : " + audioBitrate);
+ Log.v(TAG, "audioChannel : " + audioChannels);
+ Log.v(TAG, "AudioSampleRate : " + audioSamplingRate);
+
+ MediaRecorder mMediaRecorder = new MediaRecorder();
+ mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mMediaRecorder.setOutputFile(filename);
+ mMediaRecorder.setVideoFrameRate(videoFps);
+ mMediaRecorder.setVideoSize(videoWidth, videoHeight);
+ mMediaRecorder.setParameters(String.format("video-param-encoding-bitrate=%d",
+ videoBitrate));
+ mMediaRecorder.setParameters(String.format("audio-param-encoding-bitrate=%d",
+ audioBitrate));
+ mMediaRecorder.setParameters(String.format("audio-param-number-of-channels=%d",
+ audioChannels));
+ mMediaRecorder.setParameters(String.format("audio-param-sampling-rate=%d",
+ audioSamplingRate));
+ mMediaRecorder.setVideoEncoder(videoEncoder);
+ mMediaRecorder.setAudioEncoder(audioEncoder);
+ mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+ mMediaRecorder.prepare();
+ mMediaRecorder.start();
+ Thread.sleep(MediaNames.RECORDED_TIME);
+ mMediaRecorder.stop();
+ mMediaRecorder.release();
+ recordSuccess = validateVideo(filename, videoWidth, videoHeight);
+ } catch (Exception e) {
+ Log.v(TAG, e.toString());
+ return false;
+ }
+ return recordSuccess;
+ }
+
private boolean invalidRecordSetting(int frameRate, int width, int height,
int videoFormat, int outFormat, String outFile, boolean videoOnly) {
try {
@@ -356,6 +422,35 @@
MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false);
assertTrue("Invalid FrameRate", isTestInvalidFrameRateSuccessful);
}
-
+
+ @LargeTest
+ //est cases for the new codec
+ public void testDeviceSpecificCodec() throws Exception {
+ boolean recordSuccess = false;
+ String deviceType = MediaProfileReader.getDeviceType();
+ Log.v(TAG, "deviceType = " + deviceType);
+ if (deviceType.compareTo("voles") == 0) {
+ // Test cases are device specified
+ MediaProfileReader.createVideoProfileTable();
+ MediaProfileReader.createAudioProfileTable();
+ MediaProfileReader.createEncoderTable();
+ String encoderType = MediaProfileReader.getVideoCodecProperty();
+ String encoder[] = encoderType.split(",");
+ String audioType = MediaProfileReader.getAudioCodecProperty();
+ String audio[] = audioType.split(",");
+ for (int k = 0; k < 2; k++) {
+ for (int i = 0; i < encoder.length; i++) {
+ for (int j = 0; j < audio.length; j++) {
+ if (k == 0) {
+ recordSuccess = recordVideoWithPara(encoder[i], audio[j], "high");
+ } else {
+ recordSuccess = recordVideoWithPara(encoder[i], audio[j], "low");
+ }
+ assertTrue((encoder[i] + audio[j]), recordSuccess);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index b13883e..39084a7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -27,7 +27,7 @@
import android.content.res.Configuration;
import android.location.LocationManager;
import android.media.AudioManager;
-import android.os.IHardwareService;
+import android.os.IPowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
@@ -94,10 +94,10 @@
private void setBrightness(int brightness) {
try {
- IHardwareService hardware = IHardwareService.Stub
- .asInterface(ServiceManager.getService("hardware"));
- if (hardware != null) {
- hardware.setBacklights(brightness);
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ if (power != null) {
+ power.setBacklightBrightness(brightness);
}
} catch (RemoteException doe) {
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 73853595..30c25e0 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -20,6 +20,7 @@
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemClock;
import android.os.UEventObserver;
import android.util.Log;
@@ -41,8 +42,11 @@
private final Context mContext;
- public DockObserver(Context context) {
+ private PowerManagerService mPowerManager;
+
+ public DockObserver(Context context, PowerManagerService pm) {
mContext = context;
+ mPowerManager = pm;
init(); // set initial status
startObserving(DOCK_UEVENT_MATCH);
}
@@ -103,6 +107,7 @@
synchronized (this) {
Log.d(TAG, "Broadcasting dock state " + mDockState);
// Pack up the values and broadcast them to everyone
+ mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
mContext.sendStickyBroadcast(intent);
diff --git a/services/java/com/android/server/HardwareService.java b/services/java/com/android/server/HardwareService.java
index 01daae3..29c13e0 100755
--- a/services/java/com/android/server/HardwareService.java
+++ b/services/java/com/android/server/HardwareService.java
@@ -269,26 +269,6 @@
Hardware.enableCameraFlash(milliseconds);
}
- public void setBacklights(int brightness) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires HARDWARE_TEST permission");
- }
- // Don't let applications turn the screen all the way off
- brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
- setLightBrightness_UNCHECKED(LIGHT_ID_BACKLIGHT, brightness);
- setLightBrightness_UNCHECKED(LIGHT_ID_KEYBOARD, brightness);
- setLightBrightness_UNCHECKED(LIGHT_ID_BUTTONS, brightness);
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenBrightness(brightness);
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
void setLightOff_UNCHECKED(int light) {
setLight_native(mNativePointer, light, 0, LIGHT_FLASH_NONE, 0, 0);
}
@@ -307,14 +287,6 @@
setLight_native(mNativePointer, light, color, mode, onMS, offMS);
}
- public void setAutoBrightness(boolean on) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires HARDWARE_TEST permission");
- }
- setAutoBrightness_UNCHECKED(on);
- }
-
void setAutoBrightness_UNCHECKED(boolean on) {
if (mAutoBrightnessAvailable) {
setAutoBrightness_native(mNativePointer, on);
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 2951384..35f508b8 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2061,6 +2061,42 @@
return result;
}
+ public void setBacklightBrightness(int brightness) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+ // Don't let applications turn the screen all the way off
+ brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
+ mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness);
+ mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, brightness);
+ mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mBatteryStats.noteScreenBrightness(brightness);
+ } catch (RemoteException e) {
+ Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ // update our animation state
+ if (ANIMATE_SCREEN_LIGHTS) {
+ mScreenBrightness.curValue = brightness;
+ mScreenBrightness.animating = false;
+ }
+ if (ANIMATE_KEYBOARD_LIGHTS) {
+ mKeyboardBrightness.curValue = brightness;
+ mKeyboardBrightness.animating = false;
+ }
+ if (ANIMATE_BUTTON_LIGHTS) {
+ mButtonBrightness.curValue = brightness;
+ mButtonBrightness.animating = false;
+ }
+ }
+
+ public void setAutoBrightness(boolean on) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+ mHardware.setAutoBrightness_UNCHECKED(on);
+ }
+
private SensorManager getSensorManager() {
if (mSensorManager == null) {
mSensorManager = new SensorManager(mHandlerThread.getLooper());
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 7c2a7ac..b3b50e5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -330,7 +330,7 @@
try {
Log.i(TAG, "Dock Observer");
// Listen for dock station changes
- dock = new DockObserver(context);
+ dock = new DockObserver(context, power);
} catch (Throwable e) {
Log.e(TAG, "Failure starting DockObserver", e);
}
diff --git a/telephony/java/com/android/internal/telephony/SmsResponse.java b/telephony/java/com/android/internal/telephony/SmsResponse.java
index bd79e02..a7c2840 100644
--- a/telephony/java/com/android/internal/telephony/SmsResponse.java
+++ b/telephony/java/com/android/internal/telephony/SmsResponse.java
@@ -37,4 +37,12 @@
this.ackPdu = ackPdu;
this.errorCode = errorCode;
}
+
+ public String toString() {
+ String ret = "{ messageRef = " + messageRef
+ + ", errorCode = " + errorCode
+ + ", ackPdu = " + ackPdu
+ + "}";
+ return ret;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 623d985..386dc3d46 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -299,14 +299,16 @@
// Build up the data stream
ByteArrayOutputStream output = new ByteArrayOutputStream();
- for (int i = 0; i < totalSegments-1; i++) {
+ for (int i = 0; i < totalSegments; i++) {
// reassemble the (WSP-)pdu
- output.write(pdus[i], 0, pdus[i].length);
+ if (i == segment) {
+ // This one isn't in the DB, so add it
+ output.write(pdu, index, pdu.length - index);
+ } else {
+ output.write(pdus[i], 0, pdus[i].length);
+ }
}
- // This one isn't in the DB, so add it
- output.write(pdu, index, pdu.length - index);
-
byte[] datagram = output.toByteArray();
// Dispatch the PDU to applications
switch (destinationPort) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 165d583..266d127 100755
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -69,7 +69,7 @@
*/
public class SmsMessage extends SmsMessageBase {
static final String LOG_TAG = "CDMA";
- private final static Boolean DBG_SMS = false;
+ static private final String LOGGABLE_TAG = "CDMA:SMS";
/**
* Status of a previously submitted SMS.
@@ -533,7 +533,7 @@
return;
}
mBearerData = BearerData.decode(mEnvelope.bearerData);
- if (DBG_SMS) {
+ if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
Log.d(LOG_TAG, "MT raw BearerData = '" +
HexDump.toHexString(mEnvelope.bearerData) + "'");
Log.d(LOG_TAG, "MT (decoded) BearerData = " + mBearerData);
@@ -614,7 +614,7 @@
int msgId = SystemProperties.getInt(TelephonyProperties.PROPERTY_CDMA_MSG_ID, 1);
String nextMsgId = Integer.toString((msgId % 0xFFFF) + 1);
SystemProperties.set(TelephonyProperties.PROPERTY_CDMA_MSG_ID, nextMsgId);
- if (DBG_SMS) {
+ if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
Log.d(LOG_TAG, "next " + TelephonyProperties.PROPERTY_CDMA_MSG_ID + " = " + nextMsgId);
Log.d(LOG_TAG, "readback gets " +
SystemProperties.get(TelephonyProperties.PROPERTY_CDMA_MSG_ID));
@@ -655,7 +655,7 @@
bearerData.userData = userData;
byte[] encodedBearerData = BearerData.encode(bearerData);
- if (DBG_SMS) {
+ if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
Log.d(LOG_TAG, "MO (encoded) BearerData = " + bearerData);
Log.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'");
}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java
index a504cd3..a9be5bd 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java
@@ -33,7 +33,7 @@
public class FileObserverTest extends AndroidTestCase {
private Observer mObserver;
private File mTestFile;
-
+
private static class Observer extends FileObserver {
public List<Map> events = Lists.newArrayList();
public int totalEvents = 0;
@@ -56,10 +56,10 @@
}
}
}
-
+
@Override
protected void setUp() throws Exception {
- mTestFile = File.createTempFile(".file_observer_test", ".txt");
+ mTestFile = File.createTempFile(".file_observer_test", ".txt");
}
@Override
@@ -68,13 +68,13 @@
mTestFile.delete();
}
}
-
+
@LargeTest
public void testRun() throws Exception {
// make file changes and wait for them
assertTrue(mTestFile.exists());
assertNotNull(mTestFile.getParent());
-
+
mObserver = new Observer(mTestFile.getParent());
mObserver.startWatching();
@@ -85,10 +85,11 @@
waitForEvent(); // modify
mTestFile.delete();
+ waitForEvent(); // modify
waitForEvent(); // delete
mObserver.stopWatching();
-
+
// Ensure that we have seen at least 3 events.
assertTrue(mObserver.totalEvents > 3);
} finally {
@@ -111,10 +112,41 @@
while (it.hasNext()) {
Map map = it.next();
- Log.i("FileObserverTest", "event: " + map.get("event").toString() + " path: " + map.get("path"));
+ Log.i("FileObserverTest", "event: " + getEventString((Integer)map.get("event")) + " path: " + map.get("path"));
}
mObserver.events.clear();
}
}
+
+ private String getEventString(int event) {
+ switch (event) {
+ case FileObserver.ACCESS:
+ return "ACCESS";
+ case FileObserver.MODIFY:
+ return "MODIFY";
+ case FileObserver.ATTRIB:
+ return "ATTRIB";
+ case FileObserver.CLOSE_WRITE:
+ return "CLOSE_WRITE";
+ case FileObserver.CLOSE_NOWRITE:
+ return "CLOSE_NOWRITE";
+ case FileObserver.OPEN:
+ return "OPEN";
+ case FileObserver.MOVED_FROM:
+ return "MOVED_FROM";
+ case FileObserver.MOVED_TO:
+ return "MOVED_TO";
+ case FileObserver.CREATE:
+ return "CREATE";
+ case FileObserver.DELETE:
+ return "DELETE";
+ case FileObserver.DELETE_SELF:
+ return "DELETE_SELF";
+ case FileObserver.MOVE_SELF:
+ return "MOVE_SELF";
+ default:
+ return "UNKNOWN";
+ }
+ }
}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java
index bd5c955..2f1a7389 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java
@@ -63,6 +63,8 @@
wl = mPm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK");
doTestWakeLock(wl);
+ doTestSetBacklightBrightness();
+
// TODO: Some sort of functional test (maybe not in the unit test here?)
// that confirms that things are really happening e.g. screen power, keyboard power.
}
@@ -121,5 +123,20 @@
// TODO: Threaded test (needs handler) to make sure timed wakelocks work too
}
-
+
+ /**
+ * Test that calling {@link android.os.IHardwareService#setBacklights(int)} requires
+ * permissions.
+ * <p>Tests permission:
+ * {@link android.Manifest.permission#DEVICE_POWER}
+ */
+ private void doTestSetBacklightBrightness() {
+ try {
+ mPm.setBacklightBrightness(0);
+ fail("setBacklights did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
}
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 4a68d72..7dd4a88 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -88,8 +88,15 @@
result_file = "/sdcard/load_test_result.txt"
shell_cmd_str = adb_cmd + " pull " + result_file + " " + results_dir
- adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
- logging.info(adb_output)
+ (adb_output, err) = subprocess.Popen(
+ shell_cmd_str, shell=True,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ if not os.path.isfile(os.path.join(results_dir, "load_test_result.txt")):
+ logging.error("Failed to pull result file.")
+ logging.error("adb stdout:")
+ logging.error(adb_output)
+ logging.error("adb stderr:")
+ logging.error(err)
logging.info("Results are stored under: " + results_dir + "/load_test_result.txt\n")
if '__main__' == __name__:
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
index 5644044..6d5996c 100644
--- a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
+++ b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
@@ -16,7 +16,7 @@
package com.android.frameworktest.settings;
-import android.os.IHardwareService;
+import android.os.IPowerManager;
import android.app.Activity;
import android.os.Bundle;
@@ -45,11 +45,11 @@
}
public void onClick(View v) {
- IHardwareService hardware = IHardwareService.Stub.asInterface(
- ServiceManager.getService("hardware"));
- if (hardware != null) {
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ if (power != null) {
try {
- hardware.setBacklights(0);
+ power.setBacklightBrightness(0);
} catch (RemoteException darn) {
}
diff --git a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
index 1ba9d66a..dc959f5 100644
--- a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
+++ b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
@@ -188,9 +188,9 @@
previousResults[3] = new ContentProviderResult(103);
ContentValues expectedValues = new ContentValues(values);
- expectedValues.put("a1", "103");
- expectedValues.put("a2", "101");
- expectedValues.put("a3", "102");
+ expectedValues.put("a1", (long) 103);
+ expectedValues.put("a2", (long) 101);
+ expectedValues.put("a3", (long) 102);
ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
.withValues(values)
diff --git a/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
index aebd68c..2290c1d 100644
--- a/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
+++ b/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
@@ -117,20 +117,4 @@
// expected
}
}
-
- /**
- * Test that calling {@link android.os.IHardwareService#setBacklights(int)} requires
- * permissions.
- * <p>Tests permission:
- * {@link android.Manifest.permission#HARDWARE_TEST}
- * @throws RemoteException
- */
- public void testSetBacklights() throws RemoteException {
- try {
- mHardwareService.setBacklights(0);
- fail("setBacklights did not throw SecurityException as expected");
- } catch (SecurityException e) {
- // expected
- }
- }
}