summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml22
-rw-r--r--core/java/android/app/Activity.java13
-rw-r--r--core/java/android/hardware/SensorManager.java18
-rw-r--r--core/java/android/inputmethodservice/SoftInputWindow.java3
-rw-r--r--core/java/android/preference/Preference.java7
-rw-r--r--core/java/android/preference/PreferenceScreen.java1
-rw-r--r--core/java/android/provider/Checkin.java5
-rw-r--r--core/java/android/provider/Gmail.java10
-rw-r--r--core/java/android/provider/MediaStore.java6
-rw-r--r--core/java/android/server/BluetoothDeviceService.java21
-rw-r--r--core/java/android/server/BluetoothEventLoop.java3
-rw-r--r--core/java/android/view/KeyEvent.java4
-rwxr-xr-xcore/java/android/view/OrientationEventListener.java20
-rw-r--r--core/java/android/view/SurfaceHolder.java2
-rw-r--r--core/java/android/view/ViewRoot.java11
-rw-r--r--core/java/android/view/WindowManagerPolicy.java17
-rwxr-xr-xcore/java/android/view/WindowOrientationListener.java20
-rw-r--r--core/java/android/webkit/WebSettings.java6
-rw-r--r--core/java/android/webkit/WebView.java116
-rw-r--r--core/java/android/webkit/WebViewCore.java9
-rw-r--r--core/java/android/webkit/gears/GearsPluginSettings.java95
-rw-r--r--core/java/android/webkit/gears/HtmlDialogAndroid.java174
-rw-r--r--core/java/android/webkit/gears/IGearsDialogService.java107
-rw-r--r--core/java/android/widget/Adapter.java2
-rw-r--r--core/java/android/widget/TextView.java16
-rw-r--r--core/java/android/widget/ZoomRing.java113
-rw-r--r--core/java/android/widget/ZoomRingController.java82
-rw-r--r--core/java/com/android/internal/widget/TextProgressBar.java1
-rw-r--r--core/java/com/google/android/util/GoogleWebContentHelper.java2
-rw-r--r--core/res/res/color/tertiary_text_dark.xml2
-rw-r--r--core/res/res/drawable/sym_action_add.pngbin0 -> 930 bytes
-rw-r--r--core/res/res/drawable/zoom_ring_track_absolute.pngbin16759 -> 19660 bytes
-rw-r--r--core/res/res/layout/google_web_content_helper_layout.xml2
-rw-r--r--core/res/res/values/attrs.xml1
-rw-r--r--include/ui/KeycodeLabels.h4
-rw-r--r--media/libmedia/AudioRecord.cpp2
-rw-r--r--media/libmedia/ToneGenerator.cpp19
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java125
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java20
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateUnitTestTemplate.java7
-rw-r--r--services/java/com/android/server/PowerManagerService.java54
-rw-r--r--services/java/com/android/server/WindowManagerService.java17
-rw-r--r--telephony/java/com/android/internal/telephony/WapPushOverSms.java211
-rw-r--r--telephony/java/com/android/internal/telephony/WspTypeDecoder.java344
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java157
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java79
-rw-r--r--tests/AndroidTests/AndroidManifest.xml2
-rw-r--r--tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java484
-rw-r--r--tools/aapt/Package.cpp10
-rw-r--r--wifi/java/android/net/wifi/WifiMonitor.java64
52 files changed, 1253 insertions, 1261 deletions
diff --git a/api/current.xml b/api/current.xml
index aa6471b..9ccb8f7 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -118963,6 +118963,17 @@
visibility="public"
>
</field>
+<field name="KEYCODE_MUTE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="91"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="KEYCODE_N"
type="int"
transient="false"
@@ -121255,6 +121266,17 @@
<parameter name="rate" type="int">
</parameter>
</constructor>
+<method name="canDetectOrientation"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="disable"
return="void"
abstract="false"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8236943..849a37d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -890,9 +890,9 @@ public class Activity extends ContextThemeWrapper
}
/**
- * Called after {@link #onCreate} or {@link #onStop} when the current
- * activity is now being displayed to the user. It will
- * be followed by {@link #onRestart}.
+ * Called after {@link #onCreate} &mdash; or after {@link #onRestart} when
+ * the activity had been stopped, but is now again being displayed to the
+ * user. It will be followed by {@link #onResume}.
*
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
@@ -907,9 +907,9 @@ public class Activity extends ContextThemeWrapper
}
/**
- * Called after {@link #onStart} when the current activity is being
+ * Called after {@link #onStop} when the current activity is being
* re-displayed to the user (the user has navigated back to it). It will
- * be followed by {@link #onResume}.
+ * be followed by {@link #onStart} and then {@link #onResume}.
*
* <p>For activities that are using raw {@link Cursor} objects (instead of
* creating them through
@@ -923,6 +923,7 @@ public class Activity extends ContextThemeWrapper
* thrown.</em></p>
*
* @see #onStop
+ * @see #onStart
* @see #onResume
*/
protected void onRestart() {
@@ -1220,7 +1221,7 @@ public class Activity extends ContextThemeWrapper
/**
* Called when you are no longer visible to the user. You will next
- * receive either {@link #onStart}, {@link #onDestroy}, or nothing,
+ * receive either {@link #onRestart}, {@link #onDestroy}, or nothing,
* depending on later user activity.
*
* <p>Note that this method may never be called, in low memory situations
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 3981f27..e232c2c 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -620,6 +620,9 @@ public class SensorManager extends IRotationWatcher.Stub
*/
@Deprecated
public boolean registerListener(SensorListener listener, int sensors, int rate) {
+ if (listener == null) {
+ return false;
+ }
boolean result = false;
result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
listener, sensors, rate) || result;
@@ -638,6 +641,9 @@ public class SensorManager extends IRotationWatcher.Stub
private boolean registerLegacyListener(int legacyType, int type,
SensorListener listener, int sensors, int rate)
{
+ if (listener == null) {
+ return false;
+ }
boolean result = false;
// Are we activating this legacy sensor?
if ((sensors & legacyType) != 0) {
@@ -693,6 +699,9 @@ public class SensorManager extends IRotationWatcher.Stub
private void unregisterLegacyListener(int legacyType, int type,
SensorListener listener, int sensors)
{
+ if (listener == null) {
+ return;
+ }
// do we know about this listener?
LegacyListener legacyListener = null;
synchronized (mLegacyListenersMap) {
@@ -800,6 +809,9 @@ public class SensorManager extends IRotationWatcher.Stub
*/
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
Handler handler) {
+ if (listener == null || sensor == null) {
+ return false;
+ }
boolean result;
int delay = -1;
switch (rate) {
@@ -856,6 +868,9 @@ public class SensorManager extends IRotationWatcher.Stub
}
private void unregisterListener(Object listener, Sensor sensor) {
+ if (listener == null || sensor == null) {
+ return;
+ }
try {
synchronized (sListeners) {
final int size = sListeners.size();
@@ -881,6 +896,9 @@ public class SensorManager extends IRotationWatcher.Stub
}
private void unregisterListener(Object listener) {
+ if (listener == null) {
+ return;
+ }
try {
synchronized (sListeners) {
final int size = sListeners.size();
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index da67c6d..c37845f 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -141,7 +141,8 @@ class SoftInputWindow extends Dialog {
lp.gravity = Gravity.BOTTOM;
lp.width = -1;
// Let the input method window's orientation follow sensor based rotation
- lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+ // Turn this off for now, it is very problematic.
+ //lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
getWindow().setAttributes(lp);
getWindow().setFlags(
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 3820f28..a255438 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -667,7 +667,6 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
* {@link SharedPreferences}. This should be unique for the package.
*
* @param key The key for the preference.
- * @see #getId()
*/
public void setKey(String key) {
mKey = key;
@@ -1460,7 +1459,6 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
* @param container The Bundle in which to save the instance of this Preference.
*
* @see #restoreHierarchyState
- * @see #dispatchSaveInstanceState
* @see #onSaveInstanceState
*/
public void saveHierarchyState(Bundle container) {
@@ -1474,7 +1472,6 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
*
* @param container The Bundle in which to save the instance of this Preference.
*
- * @see #dispatchRestoreInstanceState
* @see #saveHierarchyState
* @see #onSaveInstanceState
*/
@@ -1503,7 +1500,6 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
* The default implementation returns null.
* @see #onRestoreInstanceState
* @see #saveHierarchyState
- * @see #dispatchSaveInstanceState
*/
protected Parcelable onSaveInstanceState() {
mBaseMethodCalled = true;
@@ -1516,7 +1512,6 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
* @param container The Bundle that holds the previously saved state.
*
* @see #saveHierarchyState
- * @see #dispatchRestoreInstanceState
* @see #onRestoreInstanceState
*/
public void restoreHierarchyState(Bundle container) {
@@ -1530,7 +1525,6 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
* not want to save state for their children.
*
* @param container The Bundle that holds the previously saved state.
- * @see #dispatchSaveInstanceState
* @see #restoreHierarchyState
* @see #onRestoreInstanceState
*/
@@ -1557,7 +1551,6 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
* {@link #onSaveInstanceState}.
* @see #onSaveInstanceState
* @see #restoreHierarchyState
- * @see #dispatchRestoreInstanceState
*/
protected void onRestoreInstanceState(Parcelable state) {
mBaseMethodCalled = true;
diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java
index 9929b96..5353b53 100644
--- a/core/java/android/preference/PreferenceScreen.java
+++ b/core/java/android/preference/PreferenceScreen.java
@@ -100,7 +100,6 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi
*
* @return An adapter that provides the {@link Preference} contained in this
* {@link PreferenceScreen}.
- * @see PreferenceGroupAdapter
*/
public ListAdapter getRootAdapter() {
if (mRootAdapter == null) {
diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java
index 688e19a..0cdac53 100644
--- a/core/java/android/provider/Checkin.java
+++ b/core/java/android/provider/Checkin.java
@@ -126,6 +126,11 @@ public final class Checkin {
/** Valid tag values. Extend as necessary for your needs. */
public enum Tag {
+ BROWSER_SNAP_CENTER,
+ BROWSER_TEXT_SIZE_CHANGE,
+ BROWSER_ZOOM_OVERVIEW,
+ BROWSER_ZOOM_RING,
+ BROWSER_ZOOM_RING_DRAG,
CRASHES_REPORTED,
CRASHES_TRUNCATED,
ELAPSED_REALTIME_SEC,
diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java
index 253dd4a..5b3c223 100644
--- a/core/java/android/provider/Gmail.java
+++ b/core/java/android/provider/Gmail.java
@@ -1477,10 +1477,20 @@ public final class Gmail {
LABEL_OUTBOX, LABEL_DRAFT, LABEL_ALL,
LABEL_SPAM, LABEL_TRASH);
+
+ private static final Set<String> USER_MEANINGFUL_SYSTEM_LABELS_SET =
+ Sets.newHashSet(
+ SORTED_USER_MEANINGFUL_SYSTEM_LABELS.toArray(
+ new String[]{}));
+
public static List<String> getSortedUserMeaningfulSystemLabels() {
return SORTED_USER_MEANINGFUL_SYSTEM_LABELS;
}
+ public static Set<String> getUserMeaningfulSystemLabelsSet() {
+ return USER_MEANINGFUL_SYSTEM_LABELS_SET;
+ }
+
/**
* If you are ever tempted to remove outbox or draft from this set make sure you have a
* way to stop draft and outbox messages from getting purged before they are sent to the
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 2897b4e..b91bc9d 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -158,6 +158,12 @@ public final class MediaStore
public final static String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality";
/**
+ * Specify the maximum allowed size.
+ * @hide
+ */
+ public final static String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit";
+
+ /**
* The name of the Intent-extra used to indicate a content resolver Uri to be used to
* store the requested image or video.
*/
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java
index 86d5a1e..fa53a60 100644
--- a/core/java/android/server/BluetoothDeviceService.java
+++ b/core/java/android/server/BluetoothDeviceService.java
@@ -47,8 +47,8 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
public class BluetoothDeviceService extends IBluetoothDevice.Stub {
@@ -121,7 +121,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
* Bring down bluetooth. Returns true on success.
*
* @param saveSetting If true, disable BT in settings
- *
+ *
*/
public synchronized boolean disable(boolean saveSetting) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
@@ -172,7 +172,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
* This turns on/off the underlying hardware.
*
* @param saveSetting If true, enable BT in settings
- *
+ *
* @return True on success (so far), guaranteeing the callback with be
* notified when complete.
*/
@@ -275,6 +275,14 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();
private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>();
+ // List of all the vendor_id prefix of Bluetooth addresses for which
+ // auto pairing is not attempted
+ private final ArrayList<String> mAutoPairingBlacklisted =
+ new ArrayList<String>(Arrays.asList(
+ "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS
+ "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS
+ "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57"// Murata for Prius 2007
+ ));
public synchronized void loadBondState() {
if (!mIsEnabled) {
@@ -322,6 +330,13 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
}
+ public boolean isAutoPairingBlacklisted(String address) {
+ for (String blacklistAddress : mAutoPairingBlacklisted) {
+ if (address.startsWith(blacklistAddress)) return true;
+ }
+ return false;
+ }
+
public synchronized int getBondState(String address) {
Integer state = mState.get(address);
if (state == null) {
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 187ec2c..8b09583 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -312,7 +312,8 @@ class BluetoothEventLoop {
case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
- if (!mBluetoothService.getBondState().hasAutoPairingFailed(address)) {
+ if (!mBluetoothService.getBondState().hasAutoPairingFailed(address) &&
+ !mBluetoothService.getBondState().isAutoPairingBlacklisted(address)) {
mBluetoothService.getBondState().attempt(address);
mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000"));
return;
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index d5434b6..d6ea91c 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -117,7 +117,8 @@ public class KeyEvent implements Parcelable {
public static final int KEYCODE_PREVIOUSSONG = 88;
public static final int KEYCODE_REWIND = 89;
public static final int KEYCODE_FORWARD = 90;
- private static final int LAST_KEYCODE = KEYCODE_FORWARD;
+ public static final int KEYCODE_MUTE = 91;
+ private static final int LAST_KEYCODE = KEYCODE_MUTE;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
@@ -502,6 +503,7 @@ public class KeyEvent implements Parcelable {
case KEYCODE_ENDCALL:
case KEYCODE_VOLUME_UP:
case KEYCODE_VOLUME_DOWN:
+ case KEYCODE_MUTE:
case KEYCODE_POWER:
case KEYCODE_HEADSETHOOK:
case KEYCODE_PLAYPAUSE:
diff --git a/core/java/android/view/OrientationEventListener.java b/core/java/android/view/OrientationEventListener.java
index cddec11..391ba1e 100755
--- a/core/java/android/view/OrientationEventListener.java
+++ b/core/java/android/view/OrientationEventListener.java
@@ -69,8 +69,11 @@ public abstract class OrientationEventListener {
public OrientationEventListener(Context context, int rate) {
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
mRate = rate;
- mSensorEventListener = new SensorEventListenerImpl();
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ if (mSensor != null) {
+ // Create listener only if sensors do exist
+ mSensorEventListener = new SensorEventListenerImpl();
+ }
}
void registerListener(OrientationListener lis) {
@@ -82,6 +85,10 @@ public abstract class OrientationEventListener {
* {@link #onOrientationChanged} when the device orientation changes.
*/
public void enable() {
+ if (mSensor == null) {
+ Log.w(TAG, "Cannot detect sensors. Not enabled");
+ return;
+ }
if (mEnabled == false) {
if (localLOGV) Log.d(TAG, "OrientationEventListener enabled");
mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
@@ -93,6 +100,10 @@ public abstract class OrientationEventListener {
* Disables the OrientationEventListener.
*/
public void disable() {
+ if (mSensor == null) {
+ Log.w(TAG, "Cannot detect sensors. Invalid disable");
+ return;
+ }
if (mEnabled == true) {
if (localLOGV) Log.d(TAG, "OrientationEventListener disabled");
mSensorManager.unregisterListener(mSensorEventListener);
@@ -138,6 +149,13 @@ public abstract class OrientationEventListener {
}
}
+
+ /*
+ * Returns true if sensor is enabled and false otherwise
+ */
+ public boolean canDetectOrientation() {
+ return mSensor != null;
+ }
/**
* Called when the orientation of the device has changed.
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
index 21a72e7..3d0dda3 100644
--- a/core/java/android/view/SurfaceHolder.java
+++ b/core/java/android/view/SurfaceHolder.java
@@ -240,7 +240,7 @@ public interface SurfaceHolder {
* in particular there is no guarantee that the content of the Surface
* will remain unchanged when lockCanvas() is called again.
*
- * @see android.view.SurfaceHolder.lockCanvas
+ * @see #lockCanvas()
*
* @param canvas The Canvas previously returned by lockCanvas().
*/
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index db8829f..3cfaf1b 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1817,6 +1817,11 @@ public final class ViewRoot extends Handler implements ViewParent,
if (event != null) {
event.recycle();
}
+ // If we reach this, we delivered a trackball event to mView and
+ // mView consumed it. Because we will not translate the trackball
+ // event into a key event, touch mode will not exit, so we exit
+ // touch mode here.
+ ensureTouchMode(false);
//noinspection ReturnInsideFinallyBlock
return;
}
@@ -2140,7 +2145,7 @@ public final class ViewRoot extends Handler implements ViewParent,
}
boolean keyHandled = mView.dispatchKeyEvent(event);
- if ((!keyHandled && isDown) || (action == KeyEvent.ACTION_MULTIPLE)) {
+ if (!keyHandled && isDown) {
int direction = 0;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_LEFT:
@@ -2541,7 +2546,7 @@ public final class ViewRoot extends Handler implements ViewParent,
* for us to consider the user to be doing fast trackball movements,
* and thus apply an acceleration.
*/
- static final long FAST_MOVE_TIME = 100;
+ static final long FAST_MOVE_TIME = 150;
/**
* Scaling factor to the time (in milliseconds) between events to how
@@ -2549,7 +2554,7 @@ public final class ViewRoot extends Handler implements ViewParent,
* is < FAST_MOVE_TIME this multiplies the acceleration; when >
* FAST_MOVE_TIME it divides it.
*/
- static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/50);
+ static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/40);
float position;
float absPosition;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 051f823..0f15b17 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -129,14 +129,22 @@ public interface WindowManagerPolicy {
Rect contentFrame, Rect visibleFrame);
/**
- * Retrieve the current frame of the window. Must be called with the
- * window manager lock held.
+ * Retrieve the current frame of the window that has been assigned by
+ * the window manager. Must be called with the window manager lock held.
*
* @return Rect The rectangle holding the window frame.
*/
public Rect getFrameLw();
/**
+ * Retrieve the current frame of the window that is actually shown.
+ * Must be called with the window manager lock held.
+ *
+ * @return Rect The rectangle holding the shown window frame.
+ */
+ public Rect getShownFrameLw();
+
+ /**
* Retrieve the frame of the display that this window was last
* laid out in. Must be called with the
* window manager lock held.
@@ -273,9 +281,12 @@ public interface WindowManagerPolicy {
* false, this is based on the currently requested
* frame, which any current animation will be moving
* towards.
+ * @param onlyOpaque If true, this will only pass if the window is
+ * also opaque.
* @return Returns true if the window is both full screen and opaque
*/
- public boolean fillsScreenLw(int width, int height, boolean shownFrame);
+ public boolean fillsScreenLw(int width, int height, boolean shownFrame,
+ boolean onlyOpaque);
/**
* Returns true if this window has been shown on screen at some time in
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 4aa3f7a..5877932 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -74,8 +74,11 @@ public abstract class WindowOrientationListener {
public WindowOrientationListener(Context context, int rate) {
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
mRate = rate;
- mSensorEventListener = new SensorEventListenerImpl();
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ if (mSensor != null) {
+ // Create listener only if sensors do exist
+ mSensorEventListener = new SensorEventListenerImpl();
+ }
}
/**
@@ -83,6 +86,10 @@ public abstract class WindowOrientationListener {
* {@link #onOrientationChanged} when the device orientation changes.
*/
public void enable() {
+ if (mSensor == null) {
+ Log.w(TAG, "Cannot detect sensors. Not enabled");
+ return;
+ }
if (mEnabled == false) {
if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled");
mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
@@ -94,6 +101,10 @@ public abstract class WindowOrientationListener {
* Disables the WindowOrientationListener.
*/
public void disable() {
+ if (mSensor == null) {
+ Log.w(TAG, "Cannot detect sensors. Invalid disable");
+ return;
+ }
if (mEnabled == true) {
if (localLOGV) Log.d(TAG, "WindowOrientationListener disabled");
mSensorManager.unregisterListener(mSensorEventListener);
@@ -145,6 +156,13 @@ public abstract class WindowOrientationListener {
}
}
+ /*
+ * Returns true if sensor is enabled and false otherwise
+ */
+ public boolean canDetectOrientation() {
+ return mSensor != null;
+ }
+
/**
* Called when the orientation of the device has changed.
* orientation parameter is in degrees, ranging from 0 to 359.
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 5c470cf..4e2b2ab 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -20,6 +20,8 @@ import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
+import android.provider.Checkin;
+
import java.lang.SecurityException;
import android.content.pm.PackageManager;
@@ -408,6 +410,10 @@ public class WebSettings {
* @see WebSettings.TextSize
*/
public synchronized void setTextSize(TextSize t) {
+ if (WebView.mLogEvent && mTextSize != t ) {
+ Checkin.updateStats(mContext.getContentResolver(),
+ Checkin.Stats.Tag.BROWSER_TEXT_SIZE_CHANGE, 1, 0.0);
+ }
mTextSize = t;
postSync();
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4d9a8fb..c59a5fc 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -38,11 +38,13 @@ import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.provider.Checkin;
import android.text.IClipboard;
import android.text.Selection;
import android.text.Spannable;
import android.util.AttributeSet;
import android.util.Config;
+import android.util.EventLog;
import android.util.Log;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -450,6 +452,13 @@ public class WebView extends AbsoluteLayout
// Used to match key downs and key ups
private boolean mGotKeyDown;
+ /* package */ static boolean mLogEvent = true;
+ private static final int EVENT_LOG_ZOOM_LEVEL_CHANGE = 70101;
+ private static final int EVENT_LOG_DOUBLE_TAP_DURATION = 70102;
+
+ // for event log
+ private long mLastTouchUpTime = 0;
+
/**
* URI scheme for telephone number
*/
@@ -556,7 +565,11 @@ public class WebView extends AbsoluteLayout
private ZoomRingController.OnZoomListener mZoomListener =
new ZoomRingController.OnZoomListener() {
-
+
+ private float mClockwiseBound;
+ private float mCounterClockwiseBound;
+ private float mStartScale;
+
public void onCenter(int x, int y) {
// Don't translate when the control is invoked, hence we do nothing
// in this callback
@@ -564,6 +577,10 @@ public class WebView extends AbsoluteLayout
public void onBeginPan() {
setZoomOverviewVisible(false);
+ if (mLogEvent) {
+ Checkin.updateStats(mContext.getContentResolver(),
+ Checkin.Stats.Tag.BROWSER_ZOOM_RING_DRAG, 1, 0.0);
+ }
}
public boolean onPan(int deltaX, int deltaY) {
@@ -576,12 +593,25 @@ public class WebView extends AbsoluteLayout
public void onVisibilityChanged(boolean visible) {
if (visible) {
switchOutDrawHistory();
+ if (mMaxZoomScale - 1 > ZOOM_RING_STEPS * 0.01f) {
+ mClockwiseBound = (float) (2 * Math.PI - MAX_ZOOM_RING_ANGLE);
+ } else {
+ mClockwiseBound = (float) (2 * Math.PI);
+ }
+ mZoomRingController.setThumbClockwiseBound(mClockwiseBound);
+ if (1 - mMinZoomScale > ZOOM_RING_STEPS * 0.01f) {
+ mCounterClockwiseBound = MAX_ZOOM_RING_ANGLE;
+ } else {
+ mCounterClockwiseBound = 0;
+ }
+ mZoomRingController
+ .setThumbCounterclockwiseBound(mCounterClockwiseBound);
float angle = 0f;
- if (mActualScale > 1) {
+ if (mActualScale > 1 && mClockwiseBound < (float) (2 * Math.PI)) {
angle = -(float) Math.round(ZOOM_RING_STEPS
* (mActualScale - 1) / (mMaxZoomScale - 1))
/ ZOOM_RING_STEPS;
- } else if (mActualScale < 1) {
+ } else if (mActualScale < 1 && mCounterClockwiseBound > 0) {
angle = (float) Math.round(ZOOM_RING_STEPS
* (1 - mActualScale) / (1 - mMinZoomScale))
/ ZOOM_RING_STEPS;
@@ -590,16 +620,26 @@ public class WebView extends AbsoluteLayout
// Show the zoom overview tab on the ring
setZoomOverviewVisible(true);
+ if (mLogEvent) {
+ Checkin.updateStats(mContext.getContentResolver(),
+ Checkin.Stats.Tag.BROWSER_ZOOM_RING, 1, 0.0);
+ }
}
}
public void onBeginDrag() {
mPreviewZoomOnly = true;
+ mStartScale = mActualScale;
setZoomOverviewVisible(false);
}
public void onEndDrag() {
mPreviewZoomOnly = false;
+ if (mLogEvent) {
+ EventLog.writeEvent(EVENT_LOG_ZOOM_LEVEL_CHANGE,
+ (int) mStartScale * 100, (int) mActualScale * 100,
+ System.currentTimeMillis());
+ }
setNewZoomScale(mActualScale, true);
}
@@ -616,21 +656,21 @@ public class WebView extends AbsoluteLayout
mZoomCenterY = (float) centerY;
float scale = 1.0f;
- if (curAngle > (float) Math.PI)
- curAngle -= (float) 2 * Math.PI;
- if (curAngle > 0) {
- if (curAngle >= MAX_ZOOM_RING_ANGLE) {
+ // curAngle is [0, 2 * Math.PI)
+ if (curAngle < (float) Math.PI) {
+ if (curAngle >= mCounterClockwiseBound) {
scale = mMinZoomScale;
} else {
scale = 1 - (float) Math.round(curAngle
/ ZOOM_RING_ANGLE_UNIT) / ZOOM_RING_STEPS
* (1 - mMinZoomScale);
}
- } else if (curAngle < 0) {
- if (curAngle <= -MAX_ZOOM_RING_ANGLE) {
+ } else {
+ if (curAngle <= mClockwiseBound) {
scale = mMaxZoomScale;
} else {
- scale = 1 + (float) Math.round(-curAngle
+ scale = 1 + (float) Math.round(
+ ((float) 2 * Math.PI - curAngle)
/ ZOOM_RING_ANGLE_UNIT) / ZOOM_RING_STEPS
* (mMaxZoomScale - 1);
}
@@ -687,12 +727,11 @@ public class WebView extends AbsoluteLayout
mScroller = new Scroller(context);
mZoomRingController = new ZoomRingController(context, this);
mZoomRingController.setResetThumbAutomatically(false);
- mZoomRingController.setThumbClockwiseBound(
- (float) (2 * Math.PI - MAX_ZOOM_RING_ANGLE));
- mZoomRingController.setThumbCounterclockwiseBound(MAX_ZOOM_RING_ANGLE);
mZoomRingController.setCallback(mZoomListener);
mZoomRingController.setZoomRingTrack(
com.android.internal.R.drawable.zoom_ring_track_absolute);
+ mZoomRingController.setPannerAcceleration(160);
+ mZoomRingController.setPannerStartAcceleratingDuration(700);
createZoomRingOverviewTab();
}
@@ -730,6 +769,10 @@ public class WebView extends AbsoluteLayout
public void onClick(View v) {
// Hide the zoom ring
mZoomRingController.setVisible(false);
+ if (mLogEvent) {
+ Checkin.updateStats(mContext.getContentResolver(),
+ Checkin.Stats.Tag.BROWSER_ZOOM_OVERVIEW, 1, 0.0);
+ }
zoomScrollOut();
}});
@@ -3468,7 +3511,7 @@ public class WebView extends AbsoluteLayout
// update mMinZoomScale
if (mMinContentWidth > MAX_FLOAT_CONTENT_WIDTH) {
boolean atMin = Math.abs(mActualScale - mMinZoomScale) < 0.01f;
- mMinZoomScale = (float) getViewWidth() / mMinContentWidth;
+ mMinZoomScale = (float) getViewWidth() / mContentWidth;
if (atMin) {
// if the WebView was at the minimum zoom scale, keep it. e,g.,
// the WebView was at the minimum zoom scale at the portrait
@@ -3535,7 +3578,8 @@ public class WebView extends AbsoluteLayout
return false;
}
- if (mShowZoomRingTutorial && mMinZoomScale < mMaxZoomScale) {
+ if (mShowZoomRingTutorial && getSettings().supportZoom()
+ && (mMaxZoomScale - mMinZoomScale) > ZOOM_RING_STEPS * 0.01f) {
ZoomRingController.showZoomTutorialOnce(mContext);
mShowZoomRingTutorial = false;
mPrivateHandler.sendMessageDelayed(mPrivateHandler
@@ -3616,10 +3660,18 @@ public class WebView extends AbsoluteLayout
mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
mZoomRingController.setVisible(true);
mInZoomTapDragMode = true;
+ if (mLogEvent) {
+ EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION,
+ (eventTime - mLastTouchUpTime), eventTime);
+ }
return mZoomRingController.handleDoubleTapEvent(ev);
} else {
mTouchMode = TOUCH_INIT_MODE;
mPreventDrag = mForwardTouchEvents;
+ if (mLogEvent && eventTime - mLastTouchUpTime < 1000) {
+ EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION,
+ (eventTime - mLastTouchUpTime), eventTime);
+ }
}
// don't trigger the link if zoom ring is visible
if (mTouchMode == TOUCH_INIT_MODE
@@ -3783,17 +3835,23 @@ public class WebView extends AbsoluteLayout
break;
}
case MotionEvent.ACTION_UP: {
+ mLastTouchUpTime = eventTime;
switch (mTouchMode) {
case TOUCH_INIT_MODE: // tap
if (mZoomRingController.isVisible()) {
- // don't trigger the link if zoom ring is visible
+ // don't trigger the link if zoom ring is visible,
+ // but still allow the double tap
+ mPrivateHandler.sendMessageDelayed(mPrivateHandler
+ .obtainMessage(RELEASE_SINGLE_TAP,
+ new Boolean(false)),
+ DOUBLE_TAP_TIMEOUT);
break;
}
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
- if (getSettings().supportZoom()
- && (mMinZoomScale < mMaxZoomScale)) {
+ if (getSettings().supportZoom()) {
mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(RELEASE_SINGLE_TAP),
+ .obtainMessage(RELEASE_SINGLE_TAP,
+ new Boolean(true)),
DOUBLE_TAP_TIMEOUT);
} else {
// do short press now
@@ -3841,7 +3899,8 @@ public class WebView extends AbsoluteLayout
// as tap instead of short press.
mTouchMode = TOUCH_INIT_MODE;
mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(RELEASE_SINGLE_TAP),
+ .obtainMessage(RELEASE_SINGLE_TAP,
+ new Boolean(true)),
DOUBLE_TAP_TIMEOUT);
} else {
mTouchMode = TOUCH_DONE_MODE;
@@ -3963,6 +4022,7 @@ public class WebView extends AbsoluteLayout
+ " time=" + time
+ " mLastFocusTime=" + mLastFocusTime);
}
+ if (isInTouchMode()) requestFocusFromTouch();
return false; // let common code in onKeyDown at it
}
if (ev.getAction() == MotionEvent.ACTION_UP) {
@@ -4399,7 +4459,12 @@ public class WebView extends AbsoluteLayout
int contentX = viewToContent((int) mLastTouchX + mScrollX);
int contentY = viewToContent((int) mLastTouchY + mScrollY);
int contentSize = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- nativeMotionUp(contentX, contentY, contentSize, true);
+ if (nativeMotionUp(contentX, contentY, contentSize, true)) {
+ if (mLogEvent) {
+ Checkin.updateStats(mContext.getContentResolver(),
+ Checkin.Stats.Tag.BROWSER_SNAP_CENTER, 1, 0.0);
+ }
+ }
if (nativeUpdateFocusNode() && !mFocusNode.mIsTextField
&& !mFocusNode.mIsTextArea) {
playSoundEffect(SoundEffectConstants.CLICK);
@@ -4619,7 +4684,9 @@ public class WebView extends AbsoluteLayout
}
case RELEASE_SINGLE_TAP: {
mTouchMode = TOUCH_DONE_MODE;
- doShortPress();
+ if ((Boolean)msg.obj) {
+ doShortPress();
+ }
break;
}
case SWITCH_TO_ENTER:
@@ -4671,7 +4738,7 @@ public class WebView extends AbsoluteLayout
mMinContentWidth = msg.arg1;
if (mMinContentWidth > MAX_FLOAT_CONTENT_WIDTH) {
mMinZoomScale = (float) getViewWidth()
- / mMinContentWidth;
+ / draw.mWidthHeight.x;
}
// We update the layout (i.e. request a layout from the
// view system) if the last view size that we sent to
@@ -5236,7 +5303,8 @@ public class WebView extends AbsoluteLayout
private native Rect nativeGetNavBounds();
private native void nativeInstrumentReport();
private native void nativeMarkNodeInvalid(int node);
- private native void nativeMotionUp(int x, int y, int slop, boolean isClick);
+ // return true if the page has been scrolled
+ private native boolean nativeMotionUp(int x, int y, int slop, boolean isClick);
// returns false if it handled the key
private native boolean nativeMoveFocus(int keyCode, int count,
boolean noScroll);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 45113ab..a7261c5 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1197,6 +1197,7 @@ final class WebViewCore {
Log.w(LOGTAG, "skip viewSizeChanged as w is 0");
return;
}
+ // negative scale indicate that WebCore should reuse the current scale
float scale = (float) viewWidth / w;
if (mSettings.getUseWideViewPort()
&& (w < mViewportWidth || mViewportWidth == -1)) {
@@ -1224,7 +1225,7 @@ final class WebViewCore {
// keep the same width and screen width so that there is
// no reflow when zoom-out
width = minContentWidth;
- screenWidth = Math.min(screenWidth, viewWidth);
+ screenWidth = Math.min(screenWidth, Math.abs(viewWidth));
} else {
width = Math.max(w, minContentWidth);
}
@@ -1536,11 +1537,11 @@ final class WebViewCore {
// white space in the GMail which uses WebView for message view.
if (mWebView != null && mWebView.mHeightCanMeasure) {
mWebView.mLastHeightSent = 0;
- // Send a negative scale to indicate that WebCore should reuse the
- // current scale
+ // Send a negative screen width to indicate that WebCore should
+ // reuse the current scale
mEventHub.sendMessage(Message.obtain(null,
EventHub.VIEW_SIZE_CHANGED, mWebView.mLastWidthSent,
- mWebView.mLastHeightSent, new Integer(-1)));
+ mWebView.mLastHeightSent, -mWebView.mLastWidthSent));
}
mBrowserFrame.didFirstLayout();
diff --git a/core/java/android/webkit/gears/GearsPluginSettings.java b/core/java/android/webkit/gears/GearsPluginSettings.java
deleted file mode 100644
index d36d3fb..0000000
--- a/core/java/android/webkit/gears/GearsPluginSettings.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2008 The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.util.Log;
-import android.webkit.Plugin;
-import android.webkit.Plugin.PreferencesClickHandler;
-
-/**
- * Simple bridge class intercepting the click in the
- * browser plugin list and calling the Gears settings
- * dialog.
- */
-public class GearsPluginSettings {
-
- private static final String TAG = "Gears-J-GearsPluginSettings";
- private Context context;
-
- public GearsPluginSettings(Plugin plugin) {
- plugin.setClickHandler(new ClickHandler());
- }
-
- /**
- * We do not need to call the dialog synchronously here (doing so
- * actually cause a lot of problems as the main message loop is also
- * blocked), which is why we simply call it via a thread.
- */
- private class ClickHandler implements PreferencesClickHandler {
- public void handleClickEvent(Context aContext) {
- context = aContext;
- Thread startService = new Thread(new StartService());
- startService.run();
- }
- }
-
- private static native void runSettingsDialog(Context c);
-
- /**
- * StartService is the runnable we use to open the dialog.
- * We bind the service to serviceConnection; upon
- * onServiceConnected the dialog will be called from the
- * native side using the runSettingsDialog method.
- */
- private class StartService implements Runnable {
- public void run() {
- HtmlDialogAndroid.bindToService(context, serviceConnection);
- }
- }
-
- /**
- * ServiceConnection instance.
- * onServiceConnected is called upon connection with the service;
- * we can then safely open the dialog.
- */
- private ServiceConnection serviceConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- IGearsDialogService gearsDialogService =
- IGearsDialogService.Stub.asInterface(service);
- HtmlDialogAndroid.setGearsDialogService(gearsDialogService);
- runSettingsDialog(context);
- context.unbindService(serviceConnection);
- HtmlDialogAndroid.setGearsDialogService(null);
- }
- public void onServiceDisconnected(ComponentName className) {
- HtmlDialogAndroid.setGearsDialogService(null);
- }
- };
-}
diff --git a/core/java/android/webkit/gears/HtmlDialogAndroid.java b/core/java/android/webkit/gears/HtmlDialogAndroid.java
deleted file mode 100644
index 6209ab9..0000000
--- a/core/java/android/webkit/gears/HtmlDialogAndroid.java
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2008 The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-import android.webkit.CacheManager;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-
-/**
- * Utility class to call a modal HTML dialog on Android
- */
-public class HtmlDialogAndroid {
-
- private static final String TAG = "Gears-J-HtmlDialog";
- private static final String DIALOG_PACKAGE = "com.android.browser";
- private static final String DIALOG_SERVICE = DIALOG_PACKAGE
- + ".GearsDialogService";
- private static final String DIALOG_INTERFACE = DIALOG_PACKAGE
- + ".IGearsDialogService";
-
- private static IGearsDialogService gearsDialogService;
-
- public static void setGearsDialogService(IGearsDialogService service) {
- gearsDialogService = service;
- }
-
- /**
- * Bind to the GearsDialogService.
- */
- public static boolean bindToService(Context context,
- ServiceConnection serviceConnection) {
- Intent dialogIntent = new Intent();
- dialogIntent.setClassName(DIALOG_PACKAGE, DIALOG_SERVICE);
- dialogIntent.setAction(DIALOG_INTERFACE);
- return context.bindService(dialogIntent, serviceConnection,
- Context.BIND_AUTO_CREATE);
- }
-
- /**
- * Bind to the GearsDialogService synchronously.
- * The service is started using our own defaultServiceConnection
- * handler, and we wait until the handler notifies us.
- */
- public void synchronousBindToService(Context context) {
- try {
- if (bindToService(context, defaultServiceConnection)) {
- if (gearsDialogService == null) {
- synchronized(defaultServiceConnection) {
- defaultServiceConnection.wait(3000); // timeout after 3s
- }
- }
- }
- } catch (InterruptedException e) {
- Log.e(TAG, "exception: " + e);
- }
- }
-
- /**
- * Read the HTML content from the disk
- */
- public String readHTML(String filePath) {
- FileInputStream inputStream = null;
- String content = "";
- try {
- inputStream = new FileInputStream(filePath);
- StringBuffer out = new StringBuffer();
- byte[] buffer = new byte[4096];
- for (int n; (n = inputStream.read(buffer)) != -1;) {
- out.append(new String(buffer, 0, n));
- }
- content = out.toString();
- } catch (IOException e) {
- Log.e(TAG, "exception: " + e);
- } finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- Log.e(TAG, "exception: " + e);
- }
- }
- }
- return content;
- }
-
- /**
- * Open an HTML dialog synchronously and waits for its completion.
- * The dialog is accessed through the GearsDialogService provided by
- * the Android Browser.
- * We can be called either directly, and then gearsDialogService will
- * not be set and we will bind to the service synchronously, and unbind
- * after calling the service, or called indirectly via GearsPluginSettings.
- * In the latter case, GearsPluginSettings does the binding/unbinding.
- */
- public String showDialog(Context context, String htmlFilePath,
- String arguments) {
-
- CacheManager.endCacheTransaction();
-
- String ret = null;
- boolean synchronousCall = false;
- if (gearsDialogService == null) {
- synchronousCall = true;
- synchronousBindToService(context);
- }
-
- try {
- if (gearsDialogService != null) {
- String htmlContent = readHTML(htmlFilePath);
- if (htmlContent.length() > 0) {
- ret = gearsDialogService.showDialog(htmlContent, arguments,
- !synchronousCall);
- }
- } else {
- Log.e(TAG, "Could not connect to the GearsDialogService!");
- }
- if (synchronousCall) {
- context.unbindService(defaultServiceConnection);
- gearsDialogService = null;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception: " + e);
- gearsDialogService = null;
- }
-
- CacheManager.startCacheTransaction();
-
- return ret;
- }
-
- private ServiceConnection defaultServiceConnection =
- new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- synchronized (defaultServiceConnection) {
- gearsDialogService = IGearsDialogService.Stub.asInterface(service);
- defaultServiceConnection.notify();
- }
- }
- public void onServiceDisconnected(ComponentName className) {
- gearsDialogService = null;
- }
- };
-}
diff --git a/core/java/android/webkit/gears/IGearsDialogService.java b/core/java/android/webkit/gears/IGearsDialogService.java
deleted file mode 100644
index 82a3bd9..0000000
--- a/core/java/android/webkit/gears/IGearsDialogService.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * This file is auto-generated. DO NOT MODIFY.
- * Original file: android.webkit.gears/IGearsDialogService.aidl
- */
-package android.webkit.gears;
-import java.lang.String;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Binder;
-import android.os.Parcel;
-public interface IGearsDialogService extends android.os.IInterface
-{
-/** Local-side IPC implementation stub class. */
-public static abstract class Stub extends android.os.Binder implements android.webkit.gears.IGearsDialogService
-{
-private static final java.lang.String DESCRIPTOR = "com.android.browser.IGearsDialogService";
-/** Construct the stub at attach it to the interface. */
-public Stub()
-{
-this.attachInterface(this, DESCRIPTOR);
-}
-/**
- * Cast an IBinder object into an IGearsDialogService interface,
- * generating a proxy if needed.
- */
-public static android.webkit.gears.IGearsDialogService asInterface(android.os.IBinder obj)
-{
-if ((obj==null)) {
-return null;
-}
-android.webkit.gears.IGearsDialogService in = (android.webkit.gears.IGearsDialogService)obj.queryLocalInterface(DESCRIPTOR);
-if ((in!=null)) {
-return in;
-}
-return new android.webkit.gears.IGearsDialogService.Stub.Proxy(obj);
-}
-public android.os.IBinder asBinder()
-{
-return this;
-}
-public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
-{
-switch (code)
-{
-case INTERFACE_TRANSACTION:
-{
-reply.writeString(DESCRIPTOR);
-return true;
-}
-case TRANSACTION_showDialog:
-{
-data.enforceInterface(DESCRIPTOR);
-java.lang.String _arg0;
-_arg0 = data.readString();
-java.lang.String _arg1;
-_arg1 = data.readString();
-boolean _arg2;
-_arg2 = (0!=data.readInt());
-java.lang.String _result = this.showDialog(_arg0, _arg1, _arg2);
-reply.writeNoException();
-reply.writeString(_result);
-return true;
-}
-}
-return super.onTransact(code, data, reply, flags);
-}
-private static class Proxy implements android.webkit.gears.IGearsDialogService
-{
-private android.os.IBinder mRemote;
-Proxy(android.os.IBinder remote)
-{
-mRemote = remote;
-}
-public android.os.IBinder asBinder()
-{
-return mRemote;
-}
-public java.lang.String getInterfaceDescriptor()
-{
-return DESCRIPTOR;
-}
-public java.lang.String showDialog(java.lang.String htmlContent, java.lang.String dialogArguments, boolean inSettings) throws android.os.RemoteException
-{
-android.os.Parcel _data = android.os.Parcel.obtain();
-android.os.Parcel _reply = android.os.Parcel.obtain();
-java.lang.String _result;
-try {
-_data.writeInterfaceToken(DESCRIPTOR);
-_data.writeString(htmlContent);
-_data.writeString(dialogArguments);
-_data.writeInt(((inSettings)?(1):(0)));
-mRemote.transact(Stub.TRANSACTION_showDialog, _data, _reply, 0);
-_reply.readException();
-_result = _reply.readString();
-}
-finally {
-_reply.recycle();
-_data.recycle();
-}
-return _result;
-}
-}
-static final int TRANSACTION_showDialog = (IBinder.FIRST_CALL_TRANSACTION + 0);
-}
-public java.lang.String showDialog(java.lang.String htmlContent, java.lang.String dialogArguments, boolean inSettings) throws android.os.RemoteException;
-}
diff --git a/core/java/android/widget/Adapter.java b/core/java/android/widget/Adapter.java
index e952dd5..f2b3e2a 100644
--- a/core/java/android/widget/Adapter.java
+++ b/core/java/android/widget/Adapter.java
@@ -116,7 +116,7 @@ public interface Adapter {
* can be converted to the other in {@link #getView}. Note: Integers must be in the
* range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can
* also be returned.
- * @see IGNORE_ITEM_VIEW_TYPE
+ * @see #IGNORE_ITEM_VIEW_TYPE
*/
int getItemViewType(int position);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index bdc54ff..c852be5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4132,8 +4132,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
removeParcelableSpans(content, start, end);
content.replace(start, end, text.text);
}
- Selection.setSelection((Spannable)getText(),
- text.selectionStart, text.selectionEnd);
+
+ // Now set the selection position... make sure it is in range, to
+ // avoid crashes. If this is a partial update, it is possible that
+ // the underlying text may have changed, causing us problems here.
+ // Also we just don't want to trust clients to do the right thing.
+ Spannable sp = (Spannable)getText();
+ final int N = sp.length();
+ int start = text.selectionStart;
+ if (start < 0) start = 0;
+ else if (start > N) start = N;
+ int end = text.selectionEnd;
+ if (end < 0) end = 0;
+ else if (end > N) end = N;
+ Selection.setSelection(sp, start, end);
}
/**
diff --git a/core/java/android/widget/ZoomRing.java b/core/java/android/widget/ZoomRing.java
index 22881b3..a29e1a0 100644
--- a/core/java/android/widget/ZoomRing.java
+++ b/core/java/android/widget/ZoomRing.java
@@ -84,6 +84,10 @@ public class ZoomRing extends View {
private Drawable mThumbPlusArrowDrawable;
/** Shown beneath the thumb if we can still zoom out. */
private Drawable mThumbMinusArrowDrawable;
+ private static final int THUMB_ARROW_PLUS = 1 << 0;
+ private static final int THUMB_ARROW_MINUS = 1 << 1;
+ /** Bitwise-OR of {@link #THUMB_ARROW_MINUS} and {@link #THUMB_ARROW_PLUS} */
+ private int mThumbArrowsToDraw;
private static final int THUMB_ARROWS_FADE_DURATION = 300;
private long mThumbArrowsFadeStartTime;
private int mThumbArrowsAlpha = 255;
@@ -166,7 +170,7 @@ public class ZoomRing extends View {
// TODO: add padding to drawable
setBackgroundResource(R.drawable.zoom_ring_track);
// TODO get from style
- setRingBounds(30, Integer.MAX_VALUE);
+ setRingBounds(43, Integer.MAX_VALUE);
mThumbHalfHeight = mThumbDrawable.getIntrinsicHeight() / 2;
mThumbHalfWidth = mThumbDrawable.getIntrinsicWidth() / 2;
@@ -276,7 +280,7 @@ public class ZoomRing extends View {
thumbCenterX + mThumbHalfWidth,
thumbCenterY + mThumbHalfHeight);
- if (mThumbArrowsAlpha > 0) {
+ if (mThumbArrowsToDraw > 0) {
setThumbArrowsAngle(angle);
}
@@ -420,12 +424,15 @@ public class ZoomRing extends View {
switch (action) {
case MotionEvent.ACTION_DOWN:
- mCallback.onUserInteractionStarted();
-
if (time - mPreviousUpTime <= DOUBLE_TAP_DISMISS_TIMEOUT) {
mCallback.onZoomRingDismissed(true);
+ onTouchUp(time);
+
+ // Dismissing, so halt here
+ return true;
}
+ mCallback.onUserInteractionStarted();
mPreviousDownX = x;
mPreviousDownY = y;
resetState();
@@ -441,23 +448,7 @@ public class ZoomRing extends View {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
- if (mMode == MODE_MOVE_ZOOM_RING || mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
- mCallback.onZoomRingSetMovableHintVisible(false);
- if (mMode == MODE_MOVE_ZOOM_RING) {
- mCallback.onZoomRingMovingStopped();
- }
- } else if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG ||
- mMode == MODE_WAITING_FOR_DRAG_THUMB) {
- onThumbDragStopped();
-
- if (mMode == MODE_DRAG_THUMB) {
- // Animate back to a tick
- setThumbAngleAnimated(mPreviousCallbackAngle, 0);
- }
- }
-
- mPreviousUpTime = time;
- mCallback.onUserInteractionStopped();
+ onTouchUp(time);
return true;
default:
@@ -524,10 +515,9 @@ public class ZoomRing extends View {
deltaThumbAndTick = getDelta(mThumbAngle, tickAngle, !oldDirectionIsCcw);
boundAngle = getBoundIfExceeds(mThumbAngle, deltaThumbAndTick);
if (boundAngle != Integer.MIN_VALUE) {
- Log
- .d(
- TAG,
- "Tapped somewhere where the shortest distance goes through a bound, but then the opposite direction also went through a bound!");
+ // Not allowed to be here, it is between two bounds
+ mMode = MODE_IGNORE_UNTIL_UP;
+ return true;
}
}
}
@@ -574,6 +564,26 @@ public class ZoomRing extends View {
return true;
}
+
+ private void onTouchUp(long time) {
+ if (mMode == MODE_MOVE_ZOOM_RING || mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
+ mCallback.onZoomRingSetMovableHintVisible(false);
+ if (mMode == MODE_MOVE_ZOOM_RING) {
+ mCallback.onZoomRingMovingStopped();
+ }
+ } else if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG ||
+ mMode == MODE_WAITING_FOR_DRAG_THUMB) {
+ onThumbDragStopped();
+
+ if (mMode == MODE_DRAG_THUMB) {
+ // Animate back to a tick
+ setThumbAngleAnimated(mPreviousCallbackAngle, 0);
+ }
+ }
+
+ mPreviousUpTime = time;
+ mCallback.onUserInteractionStopped();
+ }
private boolean isDeltaInBounds(int startAngle, int deltaAngle) {
return getBoundIfExceeds(startAngle, deltaAngle) == Integer.MIN_VALUE;
@@ -766,9 +776,11 @@ public class ZoomRing extends View {
}
}
- int deltaAngle = getDelta(mThumbAngle, touchAngle, useDirection, ccw);
- mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER);
-
+ if (DRAW_TRAIL) {
+ int deltaAngle = getDelta(mThumbAngle, touchAngle, useDirection, ccw);
+ mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER);
+ }
+
if (animateThumbToNewAngle) {
if (useDirection) {
setThumbAngleAnimated(touchAngle, 0, ccw);
@@ -851,15 +863,10 @@ public class ZoomRing extends View {
if (DRAW_TRAIL) {
mTrail.draw(canvas);
}
-
- // If we aren't near the bounds, draw the corresponding arrows
- int callbackAngle = mPreviousCallbackAngle;
- if (callbackAngle < mThumbCwBound - RADIAN_INT_ERROR ||
- callbackAngle > mThumbCwBound + RADIAN_INT_ERROR) {
+ if ((mThumbArrowsToDraw & THUMB_ARROW_PLUS) != 0) {
mThumbPlusArrowDrawable.draw(canvas);
}
- if (callbackAngle < mThumbCcwBound - RADIAN_INT_ERROR ||
- callbackAngle > mThumbCcwBound + RADIAN_INT_ERROR) {
+ if ((mThumbArrowsToDraw & THUMB_ARROW_MINUS) != 0) {
mThumbMinusArrowDrawable.draw(canvas);
}
mThumbDrawable.draw(canvas);
@@ -875,8 +882,21 @@ public class ZoomRing extends View {
public void setThumbArrowsVisible(boolean visible) {
if (visible) {
mThumbArrowsAlpha = 255;
- mThumbPlusArrowDrawable.setAlpha(255);
- mThumbMinusArrowDrawable.setAlpha(255);
+ int callbackAngle = mPreviousCallbackAngle;
+ if (callbackAngle < mThumbCwBound - RADIAN_INT_ERROR ||
+ callbackAngle > mThumbCwBound + RADIAN_INT_ERROR) {
+ mThumbPlusArrowDrawable.setAlpha(255);
+ mThumbArrowsToDraw |= THUMB_ARROW_PLUS;
+ } else {
+ mThumbArrowsToDraw &= ~THUMB_ARROW_PLUS;
+ }
+ if (callbackAngle < mThumbCcwBound - RADIAN_INT_ERROR ||
+ callbackAngle > mThumbCcwBound + RADIAN_INT_ERROR) {
+ mThumbMinusArrowDrawable.setAlpha(255);
+ mThumbArrowsToDraw |= THUMB_ARROW_MINUS;
+ } else {
+ mThumbArrowsToDraw &= ~THUMB_ARROW_MINUS;
+ }
invalidate();
} else if (mThumbArrowsAlpha == 255) {
// Only start fade if we're fully visible (otherwise another fade is happening already)
@@ -886,17 +906,24 @@ public class ZoomRing extends View {
}
private void onThumbArrowsFadeTick() {
- if (mThumbArrowsAlpha <= 0) return;
+ if (mThumbArrowsAlpha <= 0) {
+ mThumbArrowsToDraw = 0;
+ return;
+ }
mThumbArrowsAlpha = (int)
(255 - (255 * (SystemClock.elapsedRealtime() - mThumbArrowsFadeStartTime)
/ THUMB_ARROWS_FADE_DURATION));
if (mThumbArrowsAlpha < 0) mThumbArrowsAlpha = 0;
- mThumbPlusArrowDrawable.setAlpha(mThumbArrowsAlpha);
- mThumbMinusArrowDrawable.setAlpha(mThumbArrowsAlpha);
- invalidateDrawable(mThumbPlusArrowDrawable);
- invalidateDrawable(mThumbMinusArrowDrawable);
-
+ if ((mThumbArrowsToDraw & THUMB_ARROW_PLUS) != 0) {
+ mThumbPlusArrowDrawable.setAlpha(mThumbArrowsAlpha);
+ invalidateDrawable(mThumbPlusArrowDrawable);
+ }
+ if ((mThumbArrowsToDraw & THUMB_ARROW_MINUS) != 0) {
+ mThumbMinusArrowDrawable.setAlpha(mThumbArrowsAlpha);
+ invalidateDrawable(mThumbMinusArrowDrawable);
+ }
+
if (!mHandler.hasMessages(MSG_THUMB_ARROWS_FADE_TICK)) {
mHandler.sendEmptyMessage(MSG_THUMB_ARROWS_FADE_TICK);
}
diff --git a/core/java/android/widget/ZoomRingController.java b/core/java/android/widget/ZoomRingController.java
index 31074b6..2e97fda 100644
--- a/core/java/android/widget/ZoomRingController.java
+++ b/core/java/android/widget/ZoomRingController.java
@@ -57,7 +57,7 @@ import android.view.animation.DecelerateInterpolator;
public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
View.OnTouchListener, View.OnKeyListener {
- private static final int ZOOM_RING_RADIUS_INSET = 10;
+ private static final int ZOOM_RING_RADIUS_INSET = 24;
private static final int ZOOM_RING_RECENTERING_DURATION = 500;
@@ -79,7 +79,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
private static final int MAX_PAN_GAP = 20;
private static final int MAX_INITIATE_PAN_GAP = 10;
// TODO view config
- private static final int INITIATE_PAN_DELAY = 400;
+ private static final int INITIATE_PAN_DELAY = 300;
private static final String SETTING_NAME_SHOWN_TOAST = "shown_zoom_ring_toast";
@@ -146,7 +146,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
private int mZoomRingHeight;
/** Invokes panning of owner view if the zoom ring is touching an edge. */
- private Panner mPanner = new Panner();
+ private Panner mPanner;
private long mTouchingEdgeStartTime;
private boolean mPanningEnabledForThisInteraction;
@@ -241,6 +241,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mPanner = new Panner();
mOwnerView = ownerView;
mZoomRing = new ZoomRing(context);
@@ -389,6 +390,8 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
};
}
+ mPanningArrows.setAnimation(null);
+
mHandler.post(mPostedVisibleInitializer);
// Handle configuration changes when visible
@@ -409,12 +412,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
} else {
mOwnerView.setOnTouchListener(null);
}
-
+
// No longer care about configuration changes
mContext.unregisterReceiver(mConfigurationChangedReceiver);
mWindowManager.removeView(mContainer);
-
+ mHandler.removeCallbacks(mPostedVisibleInitializer);
+
if (mCallback != null) {
mCallback.onVisibilityChanged(false);
}
@@ -464,6 +468,9 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
public boolean handleDoubleTapEvent(MotionEvent event) {
int action = event.getAction();
+ // TODO: make sure this works well with the
+ // ownerView.setOnTouchListener(this) instead of window receiving
+ // touches
if (action == MotionEvent.ACTION_DOWN) {
mTouchMode = TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT;
int x = (int) event.getX();
@@ -493,6 +500,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
mViewConfig.getScaledTouchSlop()) {
mZoomRing.setTapDragMode(true, x, y);
mTouchMode = TOUCH_MODE_FORWARDING_FOR_TAP_DRAG;
+ setTouchTargetView(mZoomRing);
}
return true;
@@ -587,7 +595,6 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
public void onZoomRingMovingStarted() {
mScroller.abortAnimation();
- mPanningEnabledForThisInteraction = false;
mTouchingEdgeStartTime = 0;
if (mCallback != null) {
mCallback.onBeginPan();
@@ -658,6 +665,8 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
if (!horizontalPanning) {
// Neither are panning, reset any timer to start pan mode
mTouchingEdgeStartTime = 0;
+ mPanningEnabledForThisInteraction = false;
+ mPanner.stop();
}
}
}
@@ -752,6 +761,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
// The ring was dismissed but we need to throw away all events until the up
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
mOwnerView.setOnTouchListener(null);
+ setTouchTargetView(null);
mReleaseTouchListenerOnUp = false;
}
@@ -763,16 +773,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
switch (action) {
case MotionEvent.ACTION_DOWN:
- targetView = mTouchTargetView =
- getViewForTouch((int) event.getRawX(), (int) event.getRawY());
- if (targetView != null) {
- targetView.getLocationInWindow(mTouchTargetLocationInWindow);
- }
+ targetView = getViewForTouch((int) event.getRawX(), (int) event.getRawY());
+ setTouchTargetView(targetView);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- mTouchTargetView = null;
+ setTouchTargetView(null);
break;
}
@@ -799,6 +806,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
}
}
+ private void setTouchTargetView(View view) {
+ mTouchTargetView = view;
+ if (view != null) {
+ view.getLocationInWindow(mTouchTargetLocationInWindow);
+ }
+ }
+
/**
* Returns the View that should receive a touch at the given coordinates.
*
@@ -950,6 +964,22 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
}
}
+ public void setPannerStartVelocity(float startVelocity) {
+ mPanner.mStartVelocity = startVelocity;
+ }
+
+ public void setPannerAcceleration(float acceleration) {
+ mPanner.mAcceleration = acceleration;
+ }
+
+ public void setPannerMaxVelocity(float maxVelocity) {
+ mPanner.mMaxVelocity = maxVelocity;
+ }
+
+ public void setPannerStartAcceleratingDuration(int duration) {
+ mPanner.mStartAcceleratingDuration = duration;
+ }
+
private class Panner implements Runnable {
private static final int RUN_DELAY = 15;
private static final float STOP_SLOWDOWN = 0.8f;
@@ -967,6 +997,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
/** The time of the last callback to pan the map/browser/etc. */
private long mPreviousCallbackTime;
+ // TODO Adjust to be DPI safe
+ private float mStartVelocity = 135;
+ private float mAcceleration = 160;
+ private float mMaxVelocity = 1000;
+ private int mStartAcceleratingDuration = 700;
+ private float mVelocity;
+
/** -100 (full left) to 0 (none) to 100 (full right) */
public void setHorizontalStrength(int horizontalStrength) {
if (mHorizontalStrength == 0 && mVerticalStrength == 0 && horizontalStrength != 0) {
@@ -1013,11 +1050,12 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
boolean firstRun = mPreviousCallbackTime == 0;
long curTime = SystemClock.elapsedRealtime();
- int panAmount = getPanAmount(mStartTime, mPreviousCallbackTime, curTime);
+ int panAmount = getPanAmount(mPreviousCallbackTime, curTime);
mPreviousCallbackTime = curTime;
if (firstRun) {
mStartTime = curTime;
+ mVelocity = mStartVelocity;
} else {
int panX = panAmount * mHorizontalStrength / 100;
int panY = panAmount * mVerticalStrength / 100;
@@ -1030,12 +1068,22 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
mUiHandler.postDelayed(this, RUN_DELAY);
}
- // TODO make setter for this value so zoom clients can have different pan rates, if they want
- private static final int PAN_VELOCITY_PX_S = 30;
- private int getPanAmount(long startTime, long previousTime, long currentTime) {
- return (int) ((currentTime - previousTime) * PAN_VELOCITY_PX_S / 100);
+ private int getPanAmount(long previousTime, long currentTime) {
+ if (mVelocity > mMaxVelocity) {
+ mVelocity = mMaxVelocity;
+ } else if (mVelocity < mMaxVelocity) {
+ // See if it's time to add in some acceleration
+ if (currentTime - mStartTime > mStartAcceleratingDuration) {
+ mVelocity += (currentTime - previousTime) * mAcceleration / 1000;
+ }
+ }
+
+ return (int) ((currentTime - previousTime) * mVelocity) / 1000;
}
+
}
+
+
public interface OnZoomListener {
void onBeginDrag();
diff --git a/core/java/com/android/internal/widget/TextProgressBar.java b/core/java/com/android/internal/widget/TextProgressBar.java
index d068865..5bf4601 100644
--- a/core/java/com/android/internal/widget/TextProgressBar.java
+++ b/core/java/com/android/internal/widget/TextProgressBar.java
@@ -104,6 +104,7 @@ public class TextProgressBar extends RelativeLayout implements OnChronometerTick
* @param durationBase Use the {@link SystemClock#elapsedRealtime} time
* base.
*/
+ @android.view.RemotableViewMethod
public void setDurationBase(long durationBase) {
mDurationBase = durationBase;
diff --git a/core/java/com/google/android/util/GoogleWebContentHelper.java b/core/java/com/google/android/util/GoogleWebContentHelper.java
index 7500ec3..2911420 100644
--- a/core/java/com/google/android/util/GoogleWebContentHelper.java
+++ b/core/java/com/google/android/util/GoogleWebContentHelper.java
@@ -206,7 +206,7 @@ public class GoogleWebContentHelper {
WebSettings settings = mWebView.getSettings();
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
- mProgressBar = mLayout.findViewById(com.android.internal.R.id.progress);
+ mProgressBar = mLayout.findViewById(com.android.internal.R.id.progressContainer);
TextView message = (TextView) mProgressBar.findViewById(com.android.internal.R.id.message);
message.setText(com.android.internal.R.string.googlewebcontenthelper_loading);
diff --git a/core/res/res/color/tertiary_text_dark.xml b/core/res/res/color/tertiary_text_dark.xml
index 7e61fc8..7ce3580 100644
--- a/core/res/res/color/tertiary_text_dark.xml
+++ b/core/res/res/color/tertiary_text_dark.xml
@@ -18,7 +18,7 @@
<item android:state_enabled="false" android:color="#808080"/>
 <item android:state_window_focused="false" android:color="#808080"/>
<item android:state_pressed="true" android:color="#808080"/>
- <item android:state_selected="true" android:color="#808080"/>
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_light"/>
<item android:color="#808080"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/drawable/sym_action_add.png b/core/res/res/drawable/sym_action_add.png
new file mode 100644
index 0000000..af637b3
--- /dev/null
+++ b/core/res/res/drawable/sym_action_add.png
Binary files differ
diff --git a/core/res/res/drawable/zoom_ring_track_absolute.png b/core/res/res/drawable/zoom_ring_track_absolute.png
index 6b38c53..0195b9e 100644
--- a/core/res/res/drawable/zoom_ring_track_absolute.png
+++ b/core/res/res/drawable/zoom_ring_track_absolute.png
Binary files differ
diff --git a/core/res/res/layout/google_web_content_helper_layout.xml b/core/res/res/layout/google_web_content_helper_layout.xml
index 7409621..40f84bf 100644
--- a/core/res/res/layout/google_web_content_helper_layout.xml
+++ b/core/res/res/layout/google_web_content_helper_layout.xml
@@ -20,7 +20,7 @@
<!-- Include the indeterminate progress dialog's layout. -->
<include
- android:id="@+id/progress"
+ android:id="@+id/progressContainer"
layout="@android:layout/progress_dialog" />
<WebView
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 6e6e074..c1a6440 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -762,6 +762,7 @@
<enum name="KEYCODE_PREVIOUSSONG" value="88" />
<enum name="KEYCODE_REWIND" value="89" />
<enum name="KEYCODE_FORWARD" value="90" />
+ <enum name="KEYCODE_MUTE" value="91" />
</attr>
<!-- ***************************************************************** -->
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index 53c1188..efa6d2b 100644
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -113,6 +113,7 @@ static const KeycodeLabel KEYCODES[] = {
{ "PREVIOUSSONG", 88 },
{ "REWIND", 89 },
{ "FORWARD", 90 },
+ { "MUTE", 91 },
// NOTE: If you add a new keycode here you must also add it to:
// (enum KeyCode, in this file)
@@ -216,7 +217,8 @@ typedef enum KeyCode {
kKeyCodeNextSong = 87,
kKeyCodePreviousSong = 88,
kKeyCodeRewind = 89,
- kKeyCodeForward = 90
+ kKeyCodeForward = 90,
+ kKeyCodeMute = 91
} KeyCode;
static const KeycodeLabel FLAGS[] = {
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 3d39181..e833c85 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -400,7 +400,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
uint32_t u = cblk->user;
uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
- if (u + framesReady > bufferEnd) {
+ if (u + framesReq > bufferEnd) {
framesReq = bufferEnd - u;
}
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 7fafc56..5416629 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -175,27 +175,28 @@ bool ToneGenerator::startTone(int toneType) {
if (mState == TONE_INIT) {
if (prepareWave()) {
LOGV("Immediate start, time %d\n", (unsigned int)(systemTime()/1000000));
-
+ lResult = true;
mState = TONE_STARTING;
mLock.unlock();
mpAudioTrack->start();
mLock.lock();
if (mState == TONE_STARTING) {
+ LOGV("Wait for start callback");
if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) {
LOGE("--- Immediate start timed out");
mState = TONE_IDLE;
+ lResult = false;
}
}
-
- if (mState == TONE_PLAYING)
- lResult = true;
+ } else {
+ mState == TONE_IDLE;
}
} else {
LOGV("Delayed start\n");
mState = TONE_RESTARTING;
if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) {
- if (mState != TONE_INIT) {
+ if (mState != TONE_IDLE) {
lResult = true;
}
LOGV("cond received");
@@ -206,7 +207,8 @@ bool ToneGenerator::startTone(int toneType) {
}
mLock.unlock();
- LOGV("Tone started, time %d\n", (unsigned int)(systemTime()/1000000));
+ LOGV_IF(lResult, "Tone started, time %d\n", (unsigned int)(systemTime()/1000000));
+ LOGW_IF(!lResult, "Tone start failed!!!, time %d\n", (unsigned int)(systemTime()/1000000));
return lResult;
}
@@ -457,8 +459,11 @@ audioCallback_EndLoop:
if (lpToneGen->prepareWave()) {
lpToneGen->mState = TONE_STARTING;
} else {
- lpToneGen->mState = TONE_INIT;
+ LOGW("Cbk restarting prepareWave() failed\n");
+ lpToneGen->mState = TONE_IDLE;
lpToneGen->mpAudioTrack->stop();
+ // Force loop exit
+ lNumSmp = 0;
}
lSignal = true;
break;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
index ae6a834..b6a0848 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
@@ -19,6 +19,8 @@ package com.android.mediaframeworktest.functional;
import com.android.mediaframeworktest.MediaFrameworkTest;
import com.android.mediaframeworktest.MediaNames;
+import android.media.AudioFormat;
+import android.media.AudioManager;
import android.media.AudioTrack;
import android.content.Context;
import android.test.ActivityInstrumentationTestCase2;
@@ -47,12 +49,127 @@ public class MediaAudioTrackTest extends ActivityInstrumentationTestCase2<MediaF
protected void tearDown() throws Exception {
super.tearDown();
}
+
+ //-----------------------------------------------------------------
+ // private class to hold test reslts
+ public class TestResults {
+ public boolean mResult = false;
+ public String mResultLog = "";
+ public TestResults(boolean b, String s) { mResult = b; mResultLog = s; }
+ }
+
+ //-----------------------------------------------------------------
+ // generic test methods
+ public TestResults constructorTestMultiSampleRate(
+ // parameters tested by this method
+ int _inTest_streamType, int _inTest_mode, int _inTest_config,
+ // parameter-dependent expected results
+ int _expected_stateForMode) {
+
+ int[] testSampleRates = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000};
+ String failedRates = "Failure for rate(s): ";
+ boolean localRes, finalRes = true;
+
+ for(int i = 0 ; i < testSampleRates.length ; i++) {
+ //Log.v("MediaAudioTrackTest", "[ constructorTestMultiSampleRate ] testing "+ testSampleRates[i]);
+ AudioTrack track = null;
+ try {
+ track = new AudioTrack(
+ _inTest_streamType,
+ testSampleRates[i],
+ _inTest_config,
+ AudioFormat.ENCODING_PCM_16BIT,
+ AudioTrack.getMinBufferSize(testSampleRates[i],
+ _inTest_config, AudioFormat.ENCODING_PCM_16BIT),//testSampleRates[i]*4
+ _inTest_mode);
+ } catch(IllegalArgumentException iae) {
+ Log.e("MediaAudioTrackTest", "[ constructorTestMultiSampleRate ] exception at SR "
+ + testSampleRates[i]+": \n" + iae);
+ }
+ if(track != null) {
+ localRes = (track.getState() == _expected_stateForMode);
+ track.release();
+ }
+ else {
+ localRes = false;
+ }
+
+ if (!localRes) {
+ //log the error for the test runner
+ failedRates += Integer.toString(testSampleRates[i]) + "Hz ";
+ //log the error for logcat
+ Log.e("MediaAudioTrackTest", "[ constructorTestMultiSampleRate ] failed to construct "
+ +"AudioTrack(streamType="+_inTest_streamType
+ +", sampleRateInHz=" + testSampleRates[i]
+ +", channelConfig=" + _inTest_config
+ +", audioFormat=AudioFormat.ENCODING_PCM_16BIT"
+ +", bufferSizeInBytes=" + AudioTrack.getMinBufferSize(testSampleRates[i],
+ _inTest_config, AudioFormat.ENCODING_PCM_16BIT)
+ +", mode="+ _inTest_mode );
+ //mark test as failed
+ finalRes = false;
+ }
+ }
+ return new TestResults(finalRes, failedRates);
+ }
+
+ //-----------------------------------------------------------------
+ // AUDIOTRACK TESTS:
+ //----------------------------------
+
+ //-----------------------------------------------------------------
+ // AudioTrack constructor and AudioTrack.getMinBufferSize(...)
+ //----------------------------------
- //Test case 1: Set the invalid volume
+ //Test case 1: constructor for streaming AudioTrack, mono, 16bit at misc valid sample rates
+ @MediumTest
+ public void testConstructorMono16MusicStream() throws Exception {
+
+ TestResults res = constructorTestMultiSampleRate(
+ AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM,
+ AudioFormat.CHANNEL_CONFIGURATION_MONO,
+ AudioTrack.STATE_INITIALIZED);
+
+ assertTrue("testConstructorMono16MusicStream: " + res.mResultLog, res.mResult);
+ }
+
+
+ //Test case 2: constructor for streaming AudioTrack, stereo, 16bit at misc valid sample rates
@MediumTest
- public void testGetMinVolume() throws Exception {
- //To Do: Create the test case for GetMinVolume
- assertTrue("testGetMinVolume", true);
+ public void testConstructorStereo16MusicStream() throws Exception {
+
+ TestResults res = constructorTestMultiSampleRate(
+ AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM,
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioTrack.STATE_INITIALIZED);
+
+ assertTrue("testConstructorStereo16MusicStream: " + res.mResultLog, res.mResult);
+ }
+
+
+ //Test case 3: constructor for static AudioTrack, mono, 16bit at misc valid sample rates
+ @MediumTest
+ public void testConstructorMono16MusicStatic() throws Exception {
+
+ TestResults res = constructorTestMultiSampleRate(
+ AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC,
+ AudioFormat.CHANNEL_CONFIGURATION_MONO,
+ AudioTrack.STATE_NO_STATIC_DATA);
+
+ assertTrue("testConstructorMono16MusicStatic: " + res.mResultLog, res.mResult);
+ }
+
+
+ //Test case 4: constructor for static AudioTrack, stereo, 16bit at misc valid sample rates
+ @MediumTest
+ public void testConstructorStereo16MusicStatic() throws Exception {
+
+ TestResults res = constructorTestMultiSampleRate(
+ AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC,
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioTrack.STATE_NO_STATIC_DATA);
+
+ assertTrue("testConstructorStereo16MusicStatic: " + res.mResultLog, res.mResult);
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java
index 0209305..da18e74 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java
@@ -88,7 +88,7 @@ import android.media.AudioManager;
toneGen = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
- for (type = ToneGenerator.TONE_PROP_BEEP; type <= ToneGenerator.TONE_PROP_PROMPT; type++) {
+ for (type = ToneGenerator.TONE_PROP_BEEP; type <= ToneGenerator.TONE_PROP_BEEP2; type++) {
if (toneGen.startTone(type)) {
Thread.sleep(1000);
toneGen.stopTone();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java
index dfd544a..134144d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java
@@ -55,7 +55,7 @@ public class MediaRecorderPrepareStateUnitTest extends AndroidTestCase implement
try {
recorder.prepare();
} catch (IOException exception) {
- fail("recorder.prepare() failed");
+ throw new RuntimeException();
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java
index 50e235b..712a758 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java
@@ -29,24 +29,22 @@ public class MediaRecorderSetOutputFileStateUnitTest extends AndroidTestCase imp
private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
/**
* 1. It is valid to call setOutputFile() in the following states:
- * {DataSourceConfigured}.
+ * {DataSourceConfigured, Initial, Initialized, Prepared, Recording, Error}.
* 2. It is invalid to call setOutputFile() in the following states:
- * {Initial, Initialized, Prepared, Recording, Error}
+ * {}
*
* @param stateErrors the MediaRecorderStateErrors to check against.
*/
public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
// Valid states.
assertTrue(!stateErrors.errorInDataSourceConfiguredState);
-
- // Invalid states.
- assertTrue(stateErrors.errorInPreparedState);
- assertTrue(stateErrors.errorInRecordingState);
- assertTrue(stateErrors.errorInErrorState);
- assertTrue(stateErrors.errorInInitialState);
- assertTrue(stateErrors.errorInInitialStateAfterReset);
- assertTrue(stateErrors.errorInInitialStateAfterStop);
- assertTrue(stateErrors.errorInInitializedState);
+ assertTrue(!stateErrors.errorInPreparedState);
+ assertTrue(!stateErrors.errorInRecordingState);
+ assertTrue(!stateErrors.errorInErrorState);
+ assertTrue(!stateErrors.errorInInitialState);
+ assertTrue(!stateErrors.errorInInitialStateAfterReset);
+ assertTrue(!stateErrors.errorInInitialStateAfterStop);
+ assertTrue(!stateErrors.errorInInitializedState);
}
public void invokeMethodUnderTest(MediaRecorder recorder) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateUnitTestTemplate.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateUnitTestTemplate.java
index f350467..9edc9aa 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateUnitTestTemplate.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateUnitTestTemplate.java
@@ -90,9 +90,15 @@ class MediaRecorderStateUnitTestTemplate extends AndroidTestCase {
}
}
+ // FIXME:
+ // In the past, stop() == reset().
+ // However, this is no longer true. The plan is to have a STOPPED state.
+ // and from STOPPED state, start can be called without the need to
+ // do the recording configuration again.
private void setMediaRecorderToInitialStateAfterStop() {
try {
mMediaRecorder.reset();
+/*
mMediaRecorder.setAudioSource(AUDIO_SOURCE);
mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
@@ -100,6 +106,7 @@ class MediaRecorderStateUnitTestTemplate extends AndroidTestCase {
mMediaRecorder.prepare();
mMediaRecorder.start();
mMediaRecorder.stop();
+*/
} catch(Exception e) {
fail("setMediaRecorderToInitialStateAfterReset: Exception " + e.getClass().getName() + " was thrown.");
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 16b5819..f41d21f 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -246,8 +246,13 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
public void acquire() {
if (!mRefCounted || mCount++ == 0) {
- PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
- MY_UID, mTag);
+ long ident = Binder.clearCallingIdentity();
+ try {
+ PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
+ MY_UID, mTag);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
@@ -1285,8 +1290,9 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
} finally {
Binder.restoreCallingIdentity(identity);
}
+ mPowerState &= ~SCREEN_ON_BIT;
if (!mScreenBrightness.animating) {
- err = turnScreenOffLocked(becauseOfUser);
+ err = screenOffFinishedAnimating(becauseOfUser);
} else {
mOffBecauseOfUser = becauseOfUser;
err = 0;
@@ -1297,33 +1303,25 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
}
}
- private int turnScreenOffLocked(boolean becauseOfUser) {
- if ((mPowerState&SCREEN_ON_BIT) != 0) {
- EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
- mTotalTouchDownTime, mTouchCycles);
- mLastTouchDown = 0;
- int err = Power.setScreenState(false);
+ private int screenOffFinishedAnimating(boolean becauseOfUser) {
+ // I don't think we need to check the current state here because all of these
+ // Power.setScreenState and sendNotificationLocked can both handle being
+ // called multiple times in the same state. -joeo
+ EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
+ mTotalTouchDownTime, mTouchCycles);
+ mLastTouchDown = 0;
+ int err = Power.setScreenState(false);
+ if (mScreenOnStartTime != 0) {
mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime;
mScreenOnStartTime = 0;
- if (err == 0) {
- //
- // FIXME(joeo)
- //
- // The problem that causes the screen not to come on is that this isn't
- // called until after the animation is done. It needs to be set right
- // away, and the anmiation's state needs to be recorded separately.
- //
- //
-
- mPowerState &= ~SCREEN_ON_BIT;
- int why = becauseOfUser
- ? WindowManagerPolicy.OFF_BECAUSE_OF_USER
- : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
- sendNotificationLocked(false, why);
- }
- return err;
}
- return 0;
+ if (err == 0) {
+ int why = becauseOfUser
+ ? WindowManagerPolicy.OFF_BECAUSE_OF_USER
+ : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
+ sendNotificationLocked(false, why);
+ }
+ return err;
}
private boolean batteryIsLow() {
@@ -1538,7 +1536,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
animating = more;
if (!more) {
if (mask == Power.SCREEN_LIGHT && curIntValue == Power.BRIGHTNESS_OFF) {
- turnScreenOffLocked(mOffBecauseOfUser);
+ screenOffFinishedAnimating(mOffBecauseOfUser);
}
}
return more;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index fc22bad..10a2d29 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -2088,6 +2088,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
}
}
int or = wtoken.requestedOrientation;
+ // If this application is fullscreen, then just take whatever
+ // orientation it has and ignores whatever is under it.
+ if (wtoken.appFullscreen) {
+ return or;
+ }
// If this application has requested an explicit orientation,
// then use it.
if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
@@ -5594,6 +5599,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
return mFrame;
}
+ public Rect getShownFrameLw() {
+ return mShownFrame;
+ }
+
public Rect getDisplayFrameLw() {
return mDisplayFrame;
}
@@ -6221,10 +6230,16 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
}
public boolean fillsScreenLw(int screenWidth, int screenHeight,
- boolean shownFrame) {
+ boolean shownFrame, boolean onlyOpaque) {
if (mSurface == null) {
return false;
}
+ if (mAppToken != null && !mAppToken.appFullscreen) {
+ return false;
+ }
+ if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
+ return false;
+ }
final Rect frame = shownFrame ? mShownFrame : mFrame;
if (frame.left <= 0 && frame.top <= 0
&& frame.right >= screenWidth
diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
new file mode 100644
index 0000000..66fa943
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.content.Intent;
+import android.provider.Telephony.Sms.Intents;
+import android.util.Config;
+import android.util.Log;
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.gsm.SimUtils;
+
+
+/**
+ * WAP push handler class.
+ *
+ * @hide
+ */
+public class WapPushOverSms {
+ private static final String LOG_TAG = "WAP PUSH";
+
+ private final GSMPhone mPhone;
+ private WspTypeDecoder pduDecoder;
+
+
+ public WapPushOverSms(GSMPhone phone) {
+ mPhone = phone;
+ }
+
+ /**
+ * Dispatches inbound messages that are in the WAP PDU format. See
+ * wap-230-wsp-20010705-a section 8 for details on the WAP PDU format.
+ *
+ * @param pdu The WAP PDU, made up of one or more SMS PDUs
+ */
+ public void dispatchWapPdu(byte[] pdu) {
+
+ if (Config.LOGD) Log.d(LOG_TAG, "Rx: " + SimUtils.bytesToHexString(pdu));
+
+ int index = 0;
+ int transactionId = pdu[index++] & 0xFF;
+ int pduType = pdu[index++] & 0xFF;
+ int headerLength = 0;
+
+ if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) &&
+ (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) {
+ if (Config.LOGD) Log.w(LOG_TAG, "Received non-PUSH WAP PDU. Type = " + pduType);
+ return;
+ }
+
+ pduDecoder = new WspTypeDecoder(pdu);
+
+ /**
+ * Parse HeaderLen(unsigned integer).
+ * From wap-230-wsp-20010705-a section 8.1.2
+ * The maximum size of a uintvar is 32 bits.
+ * So it will be encoded in no more than 5 octets.
+ */
+ if (pduDecoder.decodeUintvarInteger(index) == false) {
+ if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Header Length error.");
+ return;
+ }
+ headerLength = (int)pduDecoder.getValue32();
+ index += pduDecoder.getDecodedDataLength();
+
+ int headerStartIndex = index;
+
+ /**
+ * Parse Content-Type.
+ * From wap-230-wsp-20010705-a section 8.4.2.24
+ *
+ * Content-type-value = Constrained-media | Content-general-form
+ * Content-general-form = Value-length Media-type
+ * Media-type = (Well-known-media | Extension-Media) *(Parameter)
+ * Value-length = Short-length | (Length-quote Length)
+ * Short-length = <Any octet 0-30> (octet <= WAP_PDU_SHORT_LENGTH_MAX)
+ * Length-quote = <Octet 31> (WAP_PDU_LENGTH_QUOTE)
+ * Length = Uintvar-integer
+ */
+ if (pduDecoder.decodeContentType(index) == false) {
+ if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Header Content-Type error.");
+ return;
+ }
+ int binaryContentType;
+ String mimeType = pduDecoder.getValueString();
+ if (mimeType == null) {
+ binaryContentType = (int)pduDecoder.getValue32();
+ switch (binaryContentType) {
+ case WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_XML:
+ mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML;
+ break;
+ case WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_WBXML:
+ mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_WBXML;
+ break;
+ case WspTypeDecoder.CONTENT_TYPE_B_PUSH_SI:
+ mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SI;
+ break;
+ case WspTypeDecoder.CONTENT_TYPE_B_PUSH_SL:
+ mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SL;
+ break;
+ case WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO:
+ mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO;
+ break;
+ case WspTypeDecoder.CONTENT_TYPE_B_MMS:
+ mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS;
+ break;
+ default:
+ if (Config.LOGD) {
+ Log.w(LOG_TAG,
+ "Received PDU. Unsupported Content-Type = " + binaryContentType);
+ }
+ return;
+ }
+ } else {
+ if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML)) {
+ binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_XML;
+ } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_WBXML)) {
+ binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_WBXML;
+ } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SI)) {
+ binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_SI;
+ } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SL)) {
+ binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_SL;
+ } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO)) {
+ binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO;
+ } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS)) {
+ binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_MMS;
+ } else {
+ if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Unknown Content-Type = " + mimeType);
+ return;
+ }
+ }
+ index += pduDecoder.getDecodedDataLength();
+
+ int dataIndex = headerStartIndex + headerLength;
+ boolean dispatchedByApplication = false;
+ switch (binaryContentType) {
+ case WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO:
+ dispatchWapPdu_PushCO(pdu, transactionId, pduType);
+ dispatchedByApplication = true;
+ break;
+ case WspTypeDecoder.CONTENT_TYPE_B_MMS:
+ dispatchWapPdu_MMS(pdu, transactionId, pduType, dataIndex);
+ dispatchedByApplication = true;
+ break;
+ default:
+ break;
+ }
+ if (dispatchedByApplication == false) {
+ dispatchWapPdu_default(pdu, transactionId, pduType, mimeType, dataIndex);
+ }
+ }
+
+
+
+ private void dispatchWapPdu_default(
+ byte[] pdu, int transactionId, int pduType, String mimeType, int dataIndex) {
+ byte[] data;
+
+ data = new byte[pdu.length - dataIndex];
+ System.arraycopy(pdu, dataIndex, data, 0, data.length);
+
+ Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
+ intent.setType(mimeType);
+ intent.putExtra("transactionId", transactionId);
+ intent.putExtra("pduType", pduType);
+ intent.putExtra("data", data);
+
+ mPhone.getContext().sendBroadcast(
+ intent, "android.permission.RECEIVE_WAP_PUSH");
+ }
+
+ private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType) {
+ Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
+ intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO);
+ intent.putExtra("transactionId", transactionId);
+ intent.putExtra("pduType", pduType);
+ intent.putExtra("data", pdu);
+
+ mPhone.getContext().sendBroadcast(
+ intent, "android.permission.RECEIVE_WAP_PUSH");
+ }
+
+ private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType, int dataIndex) {
+ byte[] data;
+
+ data = new byte[pdu.length - dataIndex];
+ System.arraycopy(pdu, dataIndex, data, 0, data.length);
+
+ Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
+ intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS);
+ intent.putExtra("transactionId", transactionId);
+ intent.putExtra("pduType", pduType);
+ intent.putExtra("data", data);
+
+ mPhone.getContext().sendBroadcast(
+ intent, "android.permission.RECEIVE_MMS");
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
new file mode 100644
index 0000000..2984fa8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+
+/**
+ * Implement the WSP data type decoder.
+ *
+ * @hide
+ */
+public class WspTypeDecoder {
+
+ private static final int WAP_PDU_SHORT_LENGTH_MAX = 30;
+ private static final int WAP_PDU_LENGTH_QUOTE = 31;
+
+ public static final int PDU_TYPE_PUSH = 0x06;
+ public static final int PDU_TYPE_CONFIRMED_PUSH = 0x07;
+
+ public static final int CONTENT_TYPE_B_DRM_RIGHTS_XML = 0x4a;
+ public static final int CONTENT_TYPE_B_DRM_RIGHTS_WBXML = 0x4b;
+ public static final int CONTENT_TYPE_B_PUSH_SI = 0x2e;
+ public static final int CONTENT_TYPE_B_PUSH_SL = 0x30;
+ public static final int CONTENT_TYPE_B_PUSH_CO = 0x32;
+ public static final int CONTENT_TYPE_B_MMS = 0x3e;
+
+ public static final String CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML =
+ "application/vnd.oma.drm.rights+xml";
+ public static final String CONTENT_MIME_TYPE_B_DRM_RIGHTS_WBXML =
+ "application/vnd.oma.drm.rights+wbxml";
+ public static final String CONTENT_MIME_TYPE_B_PUSH_SI = "application/vnd.wap.sic";
+ public static final String CONTENT_MIME_TYPE_B_PUSH_SL = "application/vnd.wap.slc";
+ public static final String CONTENT_MIME_TYPE_B_PUSH_CO = "application/vnd.wap.coc";
+ public static final String CONTENT_MIME_TYPE_B_MMS = "application/vnd.wap.mms-message";
+
+ public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f;
+
+
+ byte[] wspData;
+ int dataLength;
+ long unsigned32bit;
+ String stringValue;
+
+ public WspTypeDecoder(byte[] pdu) {
+ wspData = pdu;
+ }
+
+ /**
+ * Decode the "Text-string" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Text-string" in this pdu
+ *
+ * @return false when error(not a Text-string) occur
+ * return value can be retrieved by getValueString() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeTextString(int startIndex) {
+ int index = startIndex;
+ while (wspData[index] != 0) {
+ index++;
+ }
+ dataLength = index - startIndex + 1;
+ if (wspData[startIndex] == 127) {
+ stringValue = new String(wspData, startIndex+1, dataLength - 2);
+ } else {
+ stringValue = new String(wspData, startIndex, dataLength - 1);
+ }
+ return true;
+ }
+
+ /**
+ * Decode the "Short-integer" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Short-integer" in this pdu
+ *
+ * @return false when error(not a Short-integer) occur
+ * return value can be retrieved by getValue32() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeShortInteger(int startIndex) {
+ if ((wspData[startIndex] & 0x80) == 0) {
+ return false;
+ }
+ unsigned32bit = wspData[startIndex] & 0x7f;
+ dataLength = 1;
+ return true;
+ }
+
+ /**
+ * Decode the "Long-integer" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Long-integer" in this pdu
+ *
+ * @return false when error(not a Long-integer) occur
+ * return value can be retrieved by getValue32() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeLongInteger(int startIndex) {
+ int lengthMultiOctet = wspData[startIndex] & 0xff;
+
+ if (lengthMultiOctet > WAP_PDU_SHORT_LENGTH_MAX) {
+ return false;
+ }
+ unsigned32bit = 0;
+ for (int i=1; i<=lengthMultiOctet; i++) {
+ unsigned32bit = (unsigned32bit << 8) | (wspData[startIndex+i] & 0xff);
+ }
+ dataLength = 1+lengthMultiOctet;
+ return true;
+ }
+
+ /**
+ * Decode the "Integer-Value" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Integer-Value" in this pdu
+ *
+ * @return false when error(not a Integer-Value) occur
+ * return value can be retrieved by getValue32() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeIntegerValue(int startIndex) {
+ if (decodeShortInteger(startIndex) == true) {
+ return true;
+ }
+ return decodeLongInteger(startIndex);
+ }
+
+ /**
+ * Decode the "Uintvar-integer" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Uintvar-integer" in this pdu
+ *
+ * @return false when error(not a Uintvar-integer) occur
+ * return value can be retrieved by getValue32() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeUintvarInteger(int startIndex) {
+ int index = startIndex;
+
+ unsigned32bit = 0;
+ while ((wspData[index] & 0x80) != 0) {
+ if ((index - startIndex) >= 4) {
+ return false;
+ }
+ unsigned32bit = (unsigned32bit << 7) | (wspData[index] & 0x7f);
+ index++;
+ }
+ unsigned32bit = (unsigned32bit << 7) | (wspData[index] & 0x7f);
+ dataLength = index - startIndex + 1;
+ return true;
+ }
+
+ /**
+ * Decode the "Value-length" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Value-length" in this pdu
+ *
+ * @return false when error(not a Value-length) occur
+ * return value can be retrieved by getValue32() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeValueLength(int startIndex) {
+ if ((wspData[startIndex] & 0xff) > WAP_PDU_LENGTH_QUOTE) {
+ return false;
+ }
+ if (wspData[startIndex] < WAP_PDU_LENGTH_QUOTE) {
+ unsigned32bit = wspData[startIndex];
+ dataLength = 1;
+ } else {
+ decodeUintvarInteger(startIndex+1);
+ dataLength ++;
+ }
+ return true;
+ }
+
+ /**
+ * Decode the "Extension-media" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Extension-media" in this pdu
+ *
+ * @return false when error(not a Extension-media) occur
+ * return value can be retrieved by getValueString() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeExtensionMedia(int startIndex) {
+ int index = startIndex;
+ while (wspData[index] != 0) {
+ index++;
+ }
+ dataLength = index - startIndex + 1;
+ stringValue = new String(wspData, startIndex, dataLength - 1);
+ return true;
+ }
+
+ /**
+ * Decode the "Constrained-encoding" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Constrained-encoding" in this pdu
+ *
+ * @return false when error(not a Constrained-encoding) occur
+ * return value can be retrieved first by getValueString() and second by getValue32() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeConstrainedEncoding(int startIndex) {
+ if (decodeShortInteger(startIndex) == true) {
+ stringValue = null;
+ return true;
+ }
+ return decodeExtensionMedia(startIndex);
+ }
+
+ /**
+ * Decode the "Content-type" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Content-type" in this pdu
+ *
+ * @return false when error(not a Content-type) occur
+ * return value can be retrieved first by getValueString() and second by getValue32()
+ * method length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeContentType(int startIndex) {
+ int mediaPrefixLength;
+ long mediaFieldLength;
+
+ if (decodeValueLength(startIndex) == false) {
+ return decodeConstrainedEncoding(startIndex);
+ }
+ mediaPrefixLength = getDecodedDataLength();
+ mediaFieldLength = getValue32();
+ if (decodeIntegerValue(startIndex + mediaPrefixLength) == true) {
+ dataLength += mediaPrefixLength;
+ stringValue = null;
+ return true;
+ }
+ if (decodeExtensionMedia(startIndex + mediaPrefixLength) == true) {
+ dataLength += mediaPrefixLength;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Decode the "Content length" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Content length" in this pdu
+ *
+ * @return false when error(not a Content length) occur
+ * return value can be retrieved by getValue32() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeContentLength(int startIndex) {
+ return decodeIntegerValue(startIndex);
+ }
+
+ /**
+ * Decode the "Content location" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "Content location" in this pdu
+ *
+ * @return false when error(not a Content location) occur
+ * return value can be retrieved by getValueString() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeContentLocation(int startIndex) {
+ return decodeTextString(startIndex);
+ }
+
+ /**
+ * Decode the "X-Wap-Application-Id" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "X-Wap-Application-Id" in this pdu
+ *
+ * @return false when error(not a X-Wap-Application-Id) occur
+ * return value can be retrieved first by getValueString() and second by getValue32()
+ * method length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeXWapApplicationId(int startIndex) {
+ if (decodeIntegerValue(startIndex) == true) {
+ stringValue = null;
+ return true;
+ }
+ return decodeTextString(startIndex);
+ }
+
+ /**
+ * Decode the "X-Wap-Content-URI" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "X-Wap-Content-URI" in this pdu
+ *
+ * @return false when error(not a X-Wap-Content-URI) occur
+ * return value can be retrieved by getValueString() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeXWapContentURI(int startIndex) {
+ return decodeTextString(startIndex);
+ }
+
+ /**
+ * Decode the "X-Wap-Initiator-URI" type for WSP pdu
+ *
+ * @param startIndex The starting position of the "X-Wap-Initiator-URI" in this pdu
+ *
+ * @return false when error(not a X-Wap-Initiator-URI) occur
+ * return value can be retrieved by getValueString() method
+ * length of data in pdu can be retrieved by getValue32() method
+ */
+ public boolean decodeXWapInitiatorURI(int startIndex) {
+ return decodeTextString(startIndex);
+ }
+
+ /**
+ * The data length of latest operation.
+ */
+ public int getDecodedDataLength() {
+ return dataLength;
+ }
+
+ /**
+ * The 32-bits result of latest operation.
+ */
+ public long getValue32() {
+ return unsigned32bit;
+ }
+
+ /**
+ * The String result of latest operation.
+ */
+ public String getValueString() {
+ return stringValue;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
index 4176004..6eea1d4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
@@ -37,6 +37,7 @@ import android.provider.Settings;
import android.provider.Telephony.Sms.Intents;
import android.telephony.gsm.SmsMessage;
import android.telephony.gsm.SmsManager;
+import com.android.internal.telephony.WapPushOverSms;
import android.telephony.ServiceState;
import android.util.Config;
import com.android.internal.util.HexDump;
@@ -62,37 +63,6 @@ final class SMSDispatcher extends Handler {
/** Default timeout for SMS sent query */
private static final int DEFAULT_SMS_TIMOUEOUT = 6000;
- private static final int WAP_PDU_TYPE_PUSH = 0x06;
-
- private static final int WAP_PDU_TYPE_CONFIRMED_PUSH = 0x07;
-
- private static final byte DRM_RIGHTS_XML = (byte)0xca;
-
- private static final String DRM_RIGHTS_XML_MIME_TYPE = "application/vnd.oma.drm.rights+xml";
-
- private static final byte DRM_RIGHTS_WBXML = (byte)0xcb;
-
- private static final String DRM_RIGHTS_WBXML_MIME_TYPE =
- "application/vnd.oma.drm.rights+wbxml";
-
- private static final byte WAP_SI_MIME_PORT = (byte)0xae;
-
- private static final String WAP_SI_MIME_TYPE = "application/vnd.wap.sic";
-
- private static final byte WAP_SL_MIME_PORT = (byte)0xb0;
-
- private static final String WAP_SL_MIME_TYPE = "application/vnd.wap.slc";
-
- private static final byte WAP_CO_MIME_PORT = (byte)0xb2;
-
- private static final String WAP_CO_MIME_TYPE = "application/vnd.wap.coc";
-
- private static final int WAP_PDU_SHORT_LENGTH_MAX = 30;
-
- private static final int WAP_PDU_LENGTH_QUOTE = 31;
-
- private static final String MMS_MIME_TYPE = "application/vnd.wap.mms-message";
-
private static final String[] RAW_PROJECTION = new String[] {
"pdu",
"sequence",
@@ -124,6 +94,8 @@ final class SMSDispatcher extends Handler {
private final GSMPhone mPhone;
+ private final WapPushOverSms mWapPush;
+
private final Context mContext;
private final ContentResolver mResolver;
@@ -208,6 +180,7 @@ final class SMSDispatcher extends Handler {
SMSDispatcher(GSMPhone phone) {
mPhone = phone;
+ mWapPush = new WapPushOverSms(phone);
mContext = phone.getContext();
mResolver = mContext.getContentResolver();
mCm = phone.mCM;
@@ -538,7 +511,7 @@ final class SMSDispatcher extends Handler {
if (destPort != -1) {
if (destPort == SmsHeader.PORT_WAP_PUSH) {
- dispatchWapPdu(sms.getUserData());
+ mWapPush.dispatchWapPdu(sms.getUserData());
}
// The message was sent to a port, so concoct a URI for it
dispatchPortAddressedPdus(pdus, destPort);
@@ -621,7 +594,7 @@ final class SMSDispatcher extends Handler {
}
// Handle the PUSH
- dispatchWapPdu(output.toByteArray());
+ mWapPush.dispatchWapPdu(output.toByteArray());
break;
}
@@ -663,122 +636,6 @@ final class SMSDispatcher extends Handler {
intent, "android.permission.RECEIVE_SMS");
}
- /**
- * Dispatches inbound messages that are in the WAP PDU format. See
- * wap-230-wsp-20010705-a section 8 for details on the WAP PDU format.
- *
- * @param pdu The WAP PDU, made up of one or more SMS PDUs
- */
- private void dispatchWapPdu(byte[] pdu) {
- int index = 0;
- int transactionId = pdu[index++] & 0xFF;
- int pduType = pdu[index++] & 0xFF;
- int headerLength = 0;
-
- if ((pduType != WAP_PDU_TYPE_PUSH) &&
- (pduType != WAP_PDU_TYPE_CONFIRMED_PUSH)) {
- Log.w(TAG, "Received non-PUSH WAP PDU. Type = " + pduType);
- return;
- }
-
- /**
- * Parse HeaderLen(unsigned integer).
- * From wap-230-wsp-20010705-a section 8.1.2
- * The maximum size of a uintvar is 32 bits.
- * So it will be encoded in no more than 5 octets.
- */
- int temp = 0;
- do {
- temp = pdu[index++];
- headerLength = headerLength << 7;
- headerLength |= temp & 0x7F;
- } while ((temp & 0x80) != 0);
-
- int headerStartIndex = index;
-
- /**
- * Parse Content-Type.
- * From wap-230-wsp-20010705-a section 8.4.2.24
- *
- * Content-type-value = Constrained-media | Content-general-form
- * Content-general-form = Value-length Media-type
- * Media-type = (Well-known-media | Extension-Media) *(Parameter)
- * Value-length = Short-length | (Length-quote Length)
- * Short-length = <Any octet 0-30> (octet <= WAP_PDU_SHORT_LENGTH_MAX)
- * Length-quote = <Octet 31> (WAP_PDU_LENGTH_QUOTE)
- * Length = Uintvar-integer
- */
- // Parse Value-length.
- if ((pdu[index] & 0xff) <= WAP_PDU_SHORT_LENGTH_MAX) {
- // Short-length.
- index++;
- } else if (pdu[index] == WAP_PDU_LENGTH_QUOTE) {
- // Skip Length-quote.
- index++;
- // Skip Length.
- // Now we assume 8bit is enough to store the content-type length.
- index++;
- }
- String mimeType;
- switch (pdu[headerStartIndex])
- {
- case DRM_RIGHTS_XML:
- mimeType = DRM_RIGHTS_XML_MIME_TYPE;
- break;
- case DRM_RIGHTS_WBXML:
- mimeType = DRM_RIGHTS_WBXML_MIME_TYPE;
- break;
- case WAP_SI_MIME_PORT:
- // application/vnd.wap.sic
- mimeType = WAP_SI_MIME_TYPE;
- break;
- case WAP_SL_MIME_PORT:
- mimeType = WAP_SL_MIME_TYPE;
- break;
- case WAP_CO_MIME_PORT:
- mimeType = WAP_CO_MIME_TYPE;
- break;
- default:
- int start = index;
-
- // Skip text-string.
- // Now we assume the mimetype is Extension-Media.
- while (pdu[index++] != '\0') {
- ;
- }
- mimeType = new String(pdu, start, index-start-1);
- break;
- }
-
- // XXX Skip the remainder of the header for now
- int dataIndex = headerStartIndex + headerLength;
- byte[] data;
- if (pdu[headerStartIndex] == WAP_CO_MIME_PORT)
- {
- // because SMSDispatcher can't parse push headers "Content-Location" and
- // X-Wap-Content-URI, so pass the whole push to CO application.
- data = pdu;
- } else
- {
- data = new byte[pdu.length - dataIndex];
- System.arraycopy(pdu, dataIndex, data, 0, data.length);
- }
-
- // Notify listeners about the WAP PUSH
- Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
- intent.setType(mimeType);
- intent.putExtra("transactionId", transactionId);
- intent.putExtra("pduType", pduType);
- intent.putExtra("data", data);
-
- if (mimeType.equals(MMS_MIME_TYPE)) {
- mPhone.getContext().sendBroadcast(
- intent, "android.permission.RECEIVE_MMS");
- } else {
- mPhone.getContext().sendBroadcast(
- intent, "android.permission.RECEIVE_WAP_PUSH");
- }
- }
/**
* Send a multi-part text based SMS.
@@ -913,7 +770,7 @@ final class SMSDispatcher extends Handler {
sendSms(tracker);
}
}
-
+
/**
* Send a SMS
*
diff --git a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
index f37d1eb..995173b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
@@ -35,6 +35,7 @@ import android.database.ContentObserver;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
+import android.os.PowerManager;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.SystemClock;
@@ -141,6 +142,9 @@ final class ServiceStateTracker extends Handler
// Already sent the event-log for no gprs register
private boolean mReportedGprsNoReg = false;
+ // Wake lock used while setting time of day.
+ private PowerManager.WakeLock mWakeLock;
+ private static final String WAKELOCK_TAG = "ServiceStateTracker";
// Keep track of SPN display rules, so we only broadcast intent if something changes.
private String curSpn = null;
@@ -230,7 +234,11 @@ final class ServiceStateTracker extends Handler
cellLoc = new GsmCellLocation();
newCellLoc = new GsmCellLocation();
- cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
+ PowerManager powerManager =
+ (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
+ mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
+
+ cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
cm.registerForNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
@@ -1348,42 +1356,49 @@ final class ServiceStateTracker extends Handler
return;
}
- if (getAutoTime()) {
- long millisSinceNitzReceived
- = SystemClock.elapsedRealtime() - nitzReceiveTime;
+ try {
+ mWakeLock.acquire();
- if (millisSinceNitzReceived < 0) {
- // Sanity check: something is wrong
- Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
- + "backwards since NITZ time was received, "
- + nitz);
- return;
- }
+ if (getAutoTime()) {
+ long millisSinceNitzReceived
+ = SystemClock.elapsedRealtime() - nitzReceiveTime;
+
+ if (millisSinceNitzReceived < 0) {
+ // Sanity check: something is wrong
+ Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
+ + "backwards since NITZ time was received, "
+ + nitz);
+ return;
+ }
- if (millisSinceNitzReceived > Integer.MAX_VALUE) {
- // If the time is this far off, something is wrong > 24 days!
- Log.i(LOG_TAG, "NITZ: not setting time, processing has taken "
- + (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
- + " days");
- return;
- }
+ if (millisSinceNitzReceived > Integer.MAX_VALUE) {
+ // If the time is this far off, something is wrong > 24 days!
+ Log.i(LOG_TAG, "NITZ: not setting time, processing has taken "
+ + (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
+ + " days");
+ return;
+ }
- // Note: with range checks above, cast to int is safe
- c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
+ // Note: with range checks above, cast to int is safe
+ c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
- Log.i(LOG_TAG, "NITZ: Setting time of day to " + c.getTime()
- + " NITZ receive delay(ms): " + millisSinceNitzReceived
- + " gained(ms): "
- + (c.getTimeInMillis() - System.currentTimeMillis())
- + " from " + nitz);
+ Log.i(LOG_TAG, "NITZ: Setting time of day to " + c.getTime()
+ + " NITZ receive delay(ms): " + millisSinceNitzReceived
+ + " gained(ms): "
+ + (c.getTimeInMillis() - System.currentTimeMillis())
+ + " from " + nitz);
- setAndBroadcastNetworkSetTime(c.getTimeInMillis());
- }
- SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
- saveNitzTime(c.getTimeInMillis());
- if (Config.LOGV) {
- long end = SystemClock.elapsedRealtime();
- Log.v(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
+ SystemClock.setCurrentTimeMillis(c.getTimeInMillis());
+ Log.i(LOG_TAG, "NITZ: after Setting time of day");
+ }
+ SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
+ saveNitzTime(c.getTimeInMillis());
+ if (Config.LOGV) {
+ long end = SystemClock.elapsedRealtime();
+ Log.v(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
+ }
+ } finally {
+ mWakeLock.release();
}
} catch (RuntimeException ex) {
Log.e(LOG_TAG, "NITZ: Parsing NITZ time " + nitz, ex);
diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml
index 36f7b9b..843d844 100644
--- a/tests/AndroidTests/AndroidManifest.xml
+++ b/tests/AndroidTests/AndroidManifest.xml
@@ -44,8 +44,6 @@
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
- <uses-permission android:name="android.permission.BLUETOOTH" />
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_GSERVICES" />
diff --git a/tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java b/tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java
deleted file mode 100644
index 0a60319..0000000
--- a/tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.unit_tests;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothIntent;
-import android.bluetooth.BluetoothClass;
-import android.bluetooth.IBluetoothDeviceCallback;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.SystemProperties;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import junit.framework.Assert;
-
-import java.util.List;
-import java.util.HashSet;
-
-public class BluetoothTest extends AndroidTestCase {
- private static final String TAG = "BluetoothTest";
-
- @MediumTest
- public void testBluetoothSmokeTest() throws Exception {
-
- BluetoothDevice btDevice =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
-
- // TODO: Use a more reliable check to see if this product should
- // support Bluetooth - see bug 988521
- boolean shouldSupportBluetooth = SystemProperties.get("ro.kernel.qemu").equals("0");
-
- assertFalse(shouldSupportBluetooth && btDevice == null);
- if (!shouldSupportBluetooth) {
- Log.i(TAG, "Skipping test - this device does not have bluetooth.");
- return;
- }
-
- boolean bluetoothWasEnabled = btDevice.isEnabled();
-
- if (bluetoothWasEnabled) {
- Log.i(TAG, "Bluetooth already enabled");
- } else {
- Log.i(TAG, "Enabling Bluetooth...");
- btDevice.enable();
- Log.i(TAG, "Bluetooth enabled");
- }
- Assert.assertTrue(btDevice.isEnabled());
-
- String myAddress = btDevice.getAddress();
- Assert.assertTrue(myAddress != null);
- Log.i(TAG, "My Bluetooth Address is " + myAddress);
- Assert.assertFalse(myAddress.equals("00:00:00:00:00:00"));
-
- if (!bluetoothWasEnabled) {
- Log.i(TAG, "Disabling Bluetooth...");
- btDevice.disable();
- Log.i(TAG, "Bluetooth disabled");
- }
- }
-
- private boolean listenA2dp = false;
- private void listenA2dp() {
- if (!listenA2dp) {
- listenA2dp = true;
- getContext().registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- int state = intent.getIntExtra(BluetoothA2dp.SINK_STATE, -1);
- int oldState = intent.getIntExtra(BluetoothA2dp.SINK_PREVIOUS_STATE, -1);
- Log.e(TAG, "A2DP INTENT: state = " + state + " oldState = " + oldState);
- }
- }, new IntentFilter(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION));
- }
- }
-
- @MediumTest
- public void testA2dpSmokeTest() throws Exception {
- listenA2dp();
-
- BluetoothA2dp a2dp = new BluetoothA2dp(getContext());
-
- List<String> sinks = a2dp.listConnectedSinks();
- Log.e(TAG, "listConnectedSinks()...");
- for (String sink : sinks) {
- Log.e(TAG, sink + " state = " + a2dp.getSinkState(sink));
- }
- }
-
- @MediumTest
- public void testA2dpConnect() throws Exception {
- listenA2dp();
- String address = SystemProperties.get("debug.a2dp.address", "<none>");
- BluetoothA2dp a2dp = new BluetoothA2dp(getContext());
- int result = a2dp.connectSink(address);
- Log.e(TAG, "connectSink(" + address + ") = " + result);
- }
-
- @MediumTest
- public void testA2dpDisconnect() throws Exception {
- listenA2dp();
- String address = SystemProperties.get("debug.a2dp.address", "<none>");
- BluetoothA2dp a2dp = new BluetoothA2dp(getContext());
- int result = a2dp.disconnectSink(address);
- Log.e(TAG, "disconnectSink(" + address + ") = " + result);
- }
-
- @MediumTest
- public void testBluetoothEnabled() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
-
- if (device.isEnabled()) {
- Log.i(TAG, "isEnabled() = yes");
- } else {
- Log.i(TAG, "isEnabled() = no");
- }
- }
-
- @MediumTest
- public void testEnableBluetooth() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- device.enable();
- }
-
- @MediumTest
- public void testEnableBluetoothWithCallback() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- if (!device.enable(mCallback)) {
- Log.e(TAG, "enable() failed");
- }
- }
-
- @MediumTest
- public void testDisableBluetooth() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- device.disable();
- }
-
- @LargeTest
- public void testDiscovery() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- if (device.isEnabled()) {
- getContext().registerReceiver((BroadcastReceiver)new TestDiscoveryReceiver(),
- new IntentFilter(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION));
- Log.i(TAG, "Starting discovery...");
- String result = device.startDiscovery() ? "true" : "false";
- Log.i(TAG, "startDiscovery() = " + result);
- }
- }
-
- @LargeTest
- public void testMultipleDiscovery() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- if (device.isEnabled()) {
- getContext().registerReceiver((BroadcastReceiver)new TestDiscoveryReceiver(),
- new IntentFilter(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION));
- String result;
- Log.i(TAG, "Starting multiple discovery...");
- for (int i = 0; i < 5; i++) {
- result = device.startDiscovery() ? "true" : "false";
- Log.i(TAG, "startDiscovery() = " + result);
- }
- }
- }
- private class TestDiscoveryReceiver extends BroadcastReceiver {
- @Override public void onReceive(Context context, Intent intent) {
- String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
- int deviceClass = intent.getIntExtra(BluetoothIntent.CLASS, -1);
- short rssi = intent.getShortExtra(BluetoothIntent.RSSI, (short)-1);
- Log.i(TAG, "Discovered Device: " + address + " " + deviceClass + " " + rssi);
- }
- }
-
- private IBluetoothDeviceCallback mCallback = new IBluetoothDeviceCallback.Stub() {
- public void onEnableResult(int res) {
- String result = "unknown";
- switch (res) {
- case BluetoothDevice.RESULT_SUCCESS:
- result = "success";
- break;
- case BluetoothDevice.RESULT_FAILURE:
- result = "FAILURE";
- break;
- }
- Log.i(TAG, "onEnableResult(" + result + ")");
- }
- public void onGetRemoteServiceChannelResult(String device, int channel) {}
- };
-
- @SmallTest
- public void testCreateBond() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- if (!device.createBond("01:23:45:67:89:AB")) {
- Log.e(TAG, "createBonding() failed");
- }
- }
-
- @SmallTest
- public void testIsPeriodicDiscovery() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- boolean ret = device.isPeriodicDiscovery();
- if (ret) {
- Log.i(TAG, "isPeriodicDiscovery() = TRUE");
- } else {
- Log.i(TAG, "isPeriodicDiscovery() = FALSE");
- }
- }
-
- @LargeTest
- public void testListBondings() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- String[] addresses = device.listBonds();
- if (addresses == null) {
- Log.i(TAG, "Bluetooth disabled");
- return;
- }
- for (String address : addresses) {
- String name = device.getRemoteName(address);
- Log.i(TAG, "BONDING: " + address + " (" + name + ")");
- }
- }
-
- @LargeTest
- public void testListAclConnections() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- String[] addresses = device.listAclConnections();
- if (addresses == null) {
- Log.i(TAG, "Bluetooth disabled");
- return;
- }
- for (String address : addresses) {
- String name = device.getRemoteName(address);
- Log.i(TAG, "CONNECTION: " + address + " (" + name + ")");
- }
- }
-
- @LargeTest
- public void testListRemoteDevices() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- String[] addresses = device.listRemoteDevices();
- if (addresses == null) {
- Log.i(TAG, "Bluetooth disabled");
- return;
- }
- for (String address : addresses) {
- String name = device.getRemoteName(address);
- Log.i(TAG, "KNOWN DEVICE: " + address + " (" + name + ")");
- }
- }
-
- @MediumTest
- public void testSetupBTIntentRecv() throws Exception {
- BluetoothDevice device =
- (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- Log.i(TAG, "Device not Bluetooth capable, skipping test");
- return;
- }
- if (device.isEnabled()) {
- IntentFilter filter = new IntentFilter(BluetoothIntent.ENABLED_ACTION);
- filter.addAction(BluetoothIntent.ENABLED_ACTION);
- filter.addAction(BluetoothIntent.DISABLED_ACTION);
- filter.addAction(BluetoothIntent.NAME_CHANGED_ACTION);
- filter.addAction(BluetoothIntent.DISCOVERY_STARTED_ACTION);
- filter.addAction(BluetoothIntent.DISCOVERY_COMPLETED_ACTION);
- filter.addAction(BluetoothIntent.PAIRING_REQUEST_ACTION);
- filter.addAction(BluetoothIntent.PAIRING_CANCEL_ACTION);
- filter.addAction(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION);
- filter.addAction(BluetoothIntent.REMOTE_DEVICE_DISAPPEARED_ACTION);
- filter.addAction(BluetoothIntent.REMOTE_DEVICE_CLASS_UPDATED_ACTION);
- filter.addAction(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION);
- filter.addAction(BluetoothIntent.REMOTE_DEVICE_DISCONNECT_REQUESTED_ACTION);
- filter.addAction(BluetoothIntent.REMOTE_DEVICE_DISCONNECTED_ACTION);
- filter.addAction(BluetoothIntent.REMOTE_NAME_UPDATED_ACTION);
- filter.addAction(BluetoothIntent.REMOTE_NAME_FAILED_ACTION);
- filter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
- filter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION);
- getContext().registerReceiver(
- (BroadcastReceiver)new BluetoothIntentReceiver(), filter);
- Log.i(TAG, "Listening for BLUETOOTH INTENTS....");
- } else {
- Log.e(TAG, "BT not enabled");
- }
- }
-
-
- private class BluetoothIntentReceiver extends BroadcastReceiver {
- @Override public void onReceive(Context context, Intent intent) {
- String msg = "";
-
- String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
- if (address != null) {
- msg += " address=" + address;
- }
-
- int deviceClass = intent.getIntExtra(BluetoothIntent.CLASS, BluetoothClass.ERROR);
- if (deviceClass != BluetoothClass.ERROR) {
- msg += " class=" + deviceClass;
- }
-
- int rssi = intent.getIntExtra(BluetoothIntent.RSSI, -1);
- if (rssi != -1) {
- msg += " rssi=" + rssi;
- }
-
- String name = intent.getStringExtra(BluetoothIntent.NAME);
- if (name != null) {
- msg += " name=" + name;
- }
-
- int state = intent.getIntExtra(BluetoothIntent.HEADSET_STATE, -10);
- if (state != -10) {
- msg += " headset state=" + state;
- }
- Log.i(TAG, "BLUETOOTH INTENT: " + intent.getAction() + msg);
- }
- }
-
-
- private static final int[] ALL_SERVICE_CLASSES = new int[] {
- BluetoothClass.Service.LIMITED_DISCOVERABILITY,
- BluetoothClass.Service.POSITIONING,
- BluetoothClass.Service.NETWORKING,
- BluetoothClass.Service.RENDER,
- BluetoothClass.Service.CAPTURE,
- BluetoothClass.Service.OBJECT_TRANSFER,
- BluetoothClass.Service.AUDIO,
- BluetoothClass.Service.TELEPHONY,
- BluetoothClass.Service.INFORMATION
- };
- private void assertOnlyTheseServiceClassesAreSupported(int deviceClass, HashSet<Integer> serviceClasses) {
- for (int serviceClassType : ALL_SERVICE_CLASSES) {
- Assert.assertEquals(serviceClasses.contains(new Integer(serviceClassType)),
- BluetoothClass.Service.hasService(deviceClass, serviceClassType));
- }
- }
-
- @SmallTest
- public void testDeviceClass() throws Exception {
- // This test does not require bluetooth hardware
- int deviceClass;
- HashSet<Integer> serviceClasses;
-
- deviceClass = BluetoothClass.ERROR; // bogus class
- serviceClasses = new HashSet<Integer>();
- assertOnlyTheseServiceClassesAreSupported(deviceClass, serviceClasses);
- Assert.assertEquals(BluetoothClass.ERROR, BluetoothClass.Device.Major.getDeviceMajor(deviceClass));
- Assert.assertEquals(BluetoothClass.ERROR, BluetoothClass.Device.getDevice(deviceClass));
-
- deviceClass = 0x10210C; // mac book pro
- serviceClasses = new HashSet<Integer>();
- serviceClasses.add(BluetoothClass.Service.OBJECT_TRANSFER);
- serviceClasses.add(BluetoothClass.Service.LIMITED_DISCOVERABILITY);
- assertOnlyTheseServiceClassesAreSupported(deviceClass, serviceClasses);
- Assert.assertEquals(BluetoothClass.Device.Major.COMPUTER,
- BluetoothClass.Device.Major.getDeviceMajor(deviceClass));
- Assert.assertEquals(0x10C, BluetoothClass.Device.getDevice(deviceClass));
-
- // mac book pro with some unused bits set. Expecting the same results
- deviceClass = 0xFF10210F;
- serviceClasses = new HashSet<Integer>();
- serviceClasses.add(BluetoothClass.Service.OBJECT_TRANSFER);
- serviceClasses.add(BluetoothClass.Service.LIMITED_DISCOVERABILITY);
- assertOnlyTheseServiceClassesAreSupported(deviceClass, serviceClasses);
- Assert.assertEquals(BluetoothClass.Device.Major.COMPUTER,
- BluetoothClass.Device.Major.getDeviceMajor(deviceClass));
- Assert.assertEquals(0x10C, BluetoothClass.Device.getDevice(deviceClass));
-
- deviceClass = 0x3E0100; // droid.corp.google.com
- serviceClasses = new HashSet<Integer>();
- serviceClasses.add(BluetoothClass.Service.AUDIO);
- serviceClasses.add(BluetoothClass.Service.OBJECT_TRANSFER);
- serviceClasses.add(BluetoothClass.Service.CAPTURE);
- serviceClasses.add(BluetoothClass.Service.RENDER);
- serviceClasses.add(BluetoothClass.Service.NETWORKING);
- assertOnlyTheseServiceClassesAreSupported(deviceClass, serviceClasses);
- Assert.assertEquals(BluetoothClass.Device.Major.COMPUTER,
- BluetoothClass.Device.Major.getDeviceMajor(deviceClass));
- Assert.assertEquals(0x100, BluetoothClass.Device.getDevice(deviceClass));
-
- deviceClass = 0x40020C; // Android
- serviceClasses = new HashSet<Integer>();
- serviceClasses.add(BluetoothClass.Service.TELEPHONY);
- assertOnlyTheseServiceClassesAreSupported(deviceClass, serviceClasses);
- Assert.assertEquals(BluetoothClass.Device.Major.PHONE, BluetoothClass.Device.Major.getDeviceMajor(deviceClass));
- Assert.assertEquals(0x20C, BluetoothClass.Device.getDevice(deviceClass));
-
- // Motorola T305 & Jabra BT125 & Jabra BT250V
- // This seems to be a very common headset & handsfree device code
- deviceClass = 0x200404;
- serviceClasses = new HashSet<Integer>();
- serviceClasses.add(BluetoothClass.Service.AUDIO);
- assertOnlyTheseServiceClassesAreSupported(deviceClass, serviceClasses);
- Assert.assertEquals(BluetoothClass.Device.Major.AUDIO_VIDEO,
- BluetoothClass.Device.Major.getDeviceMajor(deviceClass));
- Assert.assertEquals(BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET,
- BluetoothClass.Device.getDevice(deviceClass));
-
- // Audi UHV 0128
- deviceClass = 0x200408;
- serviceClasses = new HashSet<Integer>();
- serviceClasses.add(BluetoothClass.Service.AUDIO);
- assertOnlyTheseServiceClassesAreSupported(deviceClass, serviceClasses);
- Assert.assertEquals(BluetoothClass.Device.Major.AUDIO_VIDEO,
- BluetoothClass.Device.Major.getDeviceMajor(deviceClass));
- Assert.assertEquals(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE,
- BluetoothClass.Device.getDevice(deviceClass));
- }
-}
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index 5d9e140..eb7d6f5 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -5,6 +5,7 @@
//
#include "Main.h"
#include "AaptAssets.h"
+#include "ResourceTable.h"
#include <utils.h>
#include <utils/ZipFile.h>
@@ -190,11 +191,20 @@ bail:
ssize_t processAssets(Bundle* bundle, ZipFile* zip,
const sp<AaptAssets>& assets)
{
+ ResourceFilter filter;
+ status_t status = filter.parse(bundle->getConfigurations());
+ if (status != NO_ERROR) {
+ return -1;
+ }
+
ssize_t count = 0;
const size_t N = assets->getGroupEntries().size();
for (size_t i=0; i<N; i++) {
const AaptGroupEntry& ge = assets->getGroupEntries()[i];
+ if (!filter.match(ge.toParams())) {
+ continue;
+ }
ssize_t res = processAssets(bundle, zip, assets, ge);
if (res < 0) {
return res;
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 1799560..fc750e2 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -28,7 +28,7 @@ import java.util.regex.Matcher;
* Listens for events from the wpa_supplicant server, and passes them on
* to the {@link WifiStateTracker} for handling. Runs in its own thread.
*
- * {@hide}
+ * @hide
*/
public class WifiMonitor {
@@ -119,14 +119,8 @@ public class WifiMonitor {
private final WifiStateTracker mWifiStateTracker;
- private boolean supplicantConnected;
-
- private boolean oneShot;
-
public WifiMonitor(WifiStateTracker tracker) {
mWifiStateTracker = tracker;
- supplicantConnected = false;
- oneShot = true;
}
public void startMonitoring() {
@@ -144,10 +138,17 @@ public class WifiMonitor {
public void run() {
+ if (connectToSupplicant()) {
+ // Send a message indicating that it is now possible to send commands
+ // to the supplicant
+ mWifiStateTracker.notifySupplicantConnection();
+ } else {
+ mWifiStateTracker.notifySupplicantLost();
+ return;
+ }
+
//noinspection InfiniteLoopStatement
for (;;) {
- ensureSupplicantConnection();
-
String eventStr = WifiNative.waitForEvent();
if (eventStr == null) {
@@ -214,42 +215,32 @@ public class WifiMonitor {
handleSupplicantStateChange(eventData);
} else if (event == DRIVER_STATE) {
handleDriverEvent(eventData);
+ } else if (event == TERMINATING) {
+ mWifiStateTracker.notifySupplicantLost();
+ // If supplicant is gone, exit the thread
+ break;
} else {
handleEvent(event, eventData);
- // If supplicant is gone, exit the thread
- if (event == TERMINATING) {
- break;
- }
}
}
}
- private void ensureSupplicantConnection() {
- while (!supplicantConnected) {
- boolean connected;
+ private boolean connectToSupplicant() {
+ int connectTries = 0;
+
+ while (true) {
synchronized (mWifiStateTracker) {
- connected = WifiNative.connectToSupplicant();
- }
- if (!connected) {
- /*
- * If we fail to connect on the very first attempt, send a message
- * indicating a lost connection to the supplicant, so that the
- * receiver can initialize to the proper state.
- */
- if (oneShot) {
- oneShot = false;
- mWifiStateTracker.notifySupplicantLost();
+ if (WifiNative.connectToSupplicant()) {
+ return true;
}
+ }
+ if (connectTries++ < 3) {
nap(5);
} else {
- supplicantConnected = true;
- oneShot = false;
- // Send a message indicating that it is now possible to send commands
- // to the supplicant
- mWifiStateTracker.notifySupplicantConnection();
-
+ break;
}
}
+ return false;
}
private void handlePasswordKeyMayBeIncorrect() {
@@ -287,11 +278,6 @@ public class WifiMonitor {
mWifiStateTracker.notifyScanResultsAvailable();
break;
- case TERMINATING:
- supplicantConnected = false;
- mWifiStateTracker.notifySupplicantLost();
- break;
-
case UNKNOWN:
break;
}
@@ -370,7 +356,7 @@ public class WifiMonitor {
private static void nap(int secs) {
try {
Thread.sleep(secs * 1000);
- } catch (InterruptedException e) {
+ } catch (InterruptedException ignore) {
}
}
}