summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.xml22
-rw-r--r--core/java/android/animation/package.html2
-rw-r--r--core/java/android/app/SearchManager.java6
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java3
-rw-r--r--core/java/android/bluetooth/BluetoothPan.java276
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java8
-rw-r--r--core/java/android/bluetooth/BluetoothTetheringDataTracker.java21
-rw-r--r--core/java/android/bluetooth/IBluetooth.aidl3
-rw-r--r--core/java/android/hardware/Camera.java98
-rw-r--r--core/java/android/hardware/SensorEvent.java18
-rw-r--r--core/java/android/provider/Browser.java9
-rw-r--r--core/java/android/provider/ContactsContract.java5
-rw-r--r--core/java/android/server/BluetoothEventLoop.java2
-rw-r--r--core/java/android/server/BluetoothPanProfileHandler.java38
-rw-r--r--core/java/android/server/BluetoothService.java69
-rw-r--r--core/java/android/webkit/SelectActionModeCallback.java1
-rw-r--r--core/java/android/widget/ListAdapter.java13
-rw-r--r--core/jni/android_hardware_Camera.cpp240
-rw-r--r--core/jni/android_net_wifi_Wifi.cpp13
-rwxr-xr-xcore/res/res/values/attrs.xml71
-rw-r--r--core/res/res/values/config.xml7
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java9
-rw-r--r--core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java64
-rw-r--r--docs/html/sdk/android-3.0.jd4
-rw-r--r--docs/html/sdk/index.jd16
-rw-r--r--graphics/java/android/graphics/BitmapFactory.java2
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java12
-rw-r--r--graphics/java/android/graphics/drawable/ShapeDrawable.java7
-rw-r--r--include/camera/Camera.h23
-rw-r--r--include/camera/ICamera.h12
-rw-r--r--include/media/IMediaPlayerService.h16
-rw-r--r--include/utils/RefBase.h11
-rw-r--r--libs/camera/Camera.cpp6
-rw-r--r--libs/camera/ICamera.cpp8
-rw-r--r--libs/utils/RefBase.cpp18
-rw-r--r--media/java/android/media/MediaPlayer.java8
-rw-r--r--media/java/android/media/videoeditor/MediaArtistNativeHelper.java1
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaImageItem.java1
-rw-r--r--media/jni/android_media_MediaPlayer.cpp18
-rw-r--r--media/libmedia/IMediaPlayerService.cpp28
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp92
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h24
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp86
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h2
-rw-r--r--media/libstagefright/AwesomePlayer.cpp44
-rw-r--r--media/libstagefright/CameraSourceTimeLapse.cpp2
-rw-r--r--media/libstagefright/include/AMRExtractor.h1
-rw-r--r--media/libstagefright/include/MP3Extractor.h1
-rw-r--r--media/libstagefright/include/OggExtractor.h1
-rw-r--r--media/libstagefright/include/WAVExtractor.h1
-rw-r--r--media/libstagefright/include/avc_utils.h1
-rw-r--r--media/libstagefright/mpeg2ts/ESQueue.h1
-rw-r--r--services/camera/libcameraservice/CameraService.cpp25
-rw-r--r--services/camera/libcameraservice/CameraService.h2
-rw-r--r--services/java/com/android/server/WifiService.java12
-rw-r--r--services/surfaceflinger/Layer.cpp48
-rw-r--r--services/surfaceflinger/Layer.h3
-rw-r--r--tools/layoutlib/bridge/resources/bars/phone_system_bar.xml4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java6
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java30
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java219
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java6
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java11
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java16
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java44
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java368
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java2
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java70
98 files changed, 1904 insertions, 473 deletions
diff --git a/api/current.xml b/api/current.xml
index c4fc0e470c56..a36f0665498b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -35340,6 +35340,17 @@
visibility="public"
>
</field>
+<field name="EXTRA_NEW_SEARCH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;new_search&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EXTRA_SELECT_QUERY"
type="java.lang.String"
transient="false"
@@ -156122,6 +156133,17 @@
visibility="public"
>
</field>
+<field name="EXTRA_CREATE_NEW_TAB"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;create_new_tab&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EXTRA_HEADERS"
type="java.lang.String"
transient="false"
diff --git a/core/java/android/animation/package.html b/core/java/android/animation/package.html
index ff4326092c41..92eeb20c96be 100644
--- a/core/java/android/animation/package.html
+++ b/core/java/android/animation/package.html
@@ -15,7 +15,7 @@ behaviors.</p>
<p>
For a guide on how to use the property animation system, see the
-<a href="{@docRoot}guide/topics/media/index.html">Animation</a> developer guide.
+<a href="{@docRoot}guide/topics/graphics/animation.html">Animation</a> developer guide.
</p>
</body>
</html>
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 671501255e28..aab087fcf54f 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -138,6 +138,12 @@ public class SearchManager
public final static String EXTRA_SELECT_QUERY = "select_query";
/**
+ * Boolean extra data key for {@link Intent#ACTION_WEB_SEARCH} intents. If {@code true},
+ * this search should open a new browser window, rather than using an existing one.
+ */
+ public final static String EXTRA_NEW_SEARCH = "new_search";
+
+ /**
* Boolean extra data key for a suggestion provider to return in {@link Cursor#getExtras} to
* indicate that the search is not complete yet. This can be used by the search UI
* to indicate that a search is in progress. The suggestion provider can return partial results
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 1f4fe801e638..e1c904420a38 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1052,6 +1052,9 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.INPUT_DEVICE) {
BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
return true;
+ } else if (profile == BluetoothProfile.PAN) {
+ BluetoothPan pan = new BluetoothPan(context, listener);
+ return true;
} else {
return false;
}
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 1f07349b4c13..9ffed26f4acb 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -27,187 +27,261 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.List;
+
/**
- * @hide
+ * This class provides the APIs to control the Bluetooth Pan
+ * Profile.
+ *
+ *<p>BluetoothPan is a proxy object for controlling the Bluetooth
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothPan proxy object.
+ *
+ *<p>Each method is protected with its appropriate permission.
+ *@hide
*/
-public final class BluetoothPan {
+public final class BluetoothPan implements BluetoothProfile {
private static final String TAG = "BluetoothPan";
private static final boolean DBG = false;
- //TODO: This needs to inherit from BluetoothProfile like other profiles.
-
- /** int extra for ACTION_PAN_STATE_CHANGED */
- public static final String EXTRA_PAN_STATE = "android.bluetooth.pan.extra.STATE";
-
- /** int extra for ACTION_PAN_STATE_CHANGED */
- public static final String EXTRA_PREVIOUS_PAN_STATE =
- "android.bluetooth.pan.extra.PREVIOUS_STATE";
+ /**
+ * Intent used to broadcast the change in connection state of the Pan
+ * profile.
+ *
+ * <p>This intent will have 4 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * <li> {@link #EXTRA_LOCAL_ROLE} - Which local role the remote device is
+ * bound to. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+ *
+ * <p> {@link #EXTRA_LOCAL_ROLE} can be one of {@link #LOCAL_NAP_ROLE} or
+ * {@link #LOCAL_PANU_ROLE}
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
- /** int extra for ACTION_PAN_STATE_CHANGED */
+ /**
+ * Extra for {@link #ACTION_CONNECTION_STATE_CHANGED} intent
+ * The local role of the PAN profile that the remote device is bound to.
+ * It can be one of {@link #LOCAL_NAP_ROLE} or {@link #LOCAL_PANU_ROLE}.
+ */
public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
+ /**
+ * The local device is acting as a Network Access Point.
+ */
public static final int LOCAL_NAP_ROLE = 1;
- public static final int LOCAL_PANU_ROLE = 2;
/**
- * Indicates the state of an PAN device has changed.
- * This intent will always contain EXTRA_DEVICE_STATE,
- * EXTRA_PREVIOUS_DEVICE_STATE, BluetoothDevice.EXTRA_DEVICE
- * and EXTRA_LOCAL_ROLE.
- * extras.
+ * The local device is acting as a PAN User.
*/
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PAN_STATE_CHANGED =
- "android.bluetooth.pan.action.STATE_CHANGED";
-
- public static final String NAP_ROLE = "nap";
- public static final String NAP_BRIDGE = "pan1";
-
- public static final int MAX_CONNECTIONS = 7;
-
- public static final int STATE_DISCONNECTED = 0;
- public static final int STATE_CONNECTING = 1;
- public static final int STATE_CONNECTED = 2;
- public static final int STATE_DISCONNECTING = 3;
+ public static final int LOCAL_PANU_ROLE = 2;
/**
* Return codes for the connect and disconnect Bluez / Dbus calls.
+ * @hide
*/
public static final int PAN_DISCONNECT_FAILED_NOT_CONNECTED = 1000;
+ /**
+ * @hide
+ */
public static final int PAN_CONNECT_FAILED_ALREADY_CONNECTED = 1001;
+ /**
+ * @hide
+ */
public static final int PAN_CONNECT_FAILED_ATTEMPT_FAILED = 1002;
+ /**
+ * @hide
+ */
public static final int PAN_OPERATION_GENERIC_FAILURE = 1003;
+ /**
+ * @hide
+ */
public static final int PAN_OPERATION_SUCCESS = 1004;
- private final IBluetooth mService;
- private final Context mContext;
+ private ServiceListener mServiceListener;
+ private BluetoothAdapter mAdapter;
+ private IBluetooth mService;
/**
* Create a BluetoothPan proxy object for interacting with the local
- * Bluetooth Pan service.
- * @param c Context
+ * Bluetooth Service which handles the Pan profile
+ *
*/
- public BluetoothPan(Context c) {
- mContext = c;
-
+ /*package*/ BluetoothPan(Context mContext, ServiceListener l) {
IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
if (b != null) {
mService = IBluetooth.Stub.asInterface(b);
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.PAN, this);
+ }
} else {
Log.w(TAG, "Bluetooth Service not available!");
// Instead of throwing an exception which prevents people from going
- // into Wireless settings in the emulator. Let it crash later
- // when it is actually used.
+ // into Wireless settings in the emulator. Let it crash later when it is actually used.
mService = null;
}
}
/**
- * Initiate a PAN connection.
- *
- * This function returns false on error and true if the connection
- * attempt is being made.
- *
- * Listen for {@link #ACTION_PAN_STATE_CHANGED} to find out when the
- * connection is completed.
- *
- * @param device Remote BT device.
- * @return false on immediate error, true otherwise
+ * {@inheritDoc}
* @hide
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- try {
- return mService.connectPanDevice(device);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.connectPanDevice(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
}
/**
- * Initiate disconnect from PAN.
- *
- * This function return false on error and true if the disconnection
- * attempt is being made.
- *
- * Listen for {@link #ACTION_PAN_STATE_CHANGED} to find out when
- * disconnect is completed.
- *
- * @param device Remote BT device.
- * @return false on immediate error, true otherwise
+ * {@inheritDoc}
* @hide
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- try {
- return mService.disconnectPanDevice(device);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.disconnectPanDevice(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
}
/**
- * Get the state of a PAN Device.
- *
- * This function returns an int representing the state of the PAN connection
- *
- * @param device Remote BT device.
- * @return The current state of the PAN Device
- * @hide
+ * {@inheritDoc}
*/
- public int getPanDeviceState(BluetoothDevice device) {
- if (DBG) log("getPanDeviceState(" + device + ")");
- try {
- return mService.getPanDeviceState(device);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return STATE_DISCONNECTED;
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (DBG) log("getConnectedDevices()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getConnectedPanDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
}
/**
- * Returns a set of all the connected PAN Devices
- *
- * Does not include devices that are currently connecting or disconnecting
- *
- * @return List of PAN devices or empty on Error
+ * {@inheritDoc}
+ */
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (DBG) log("getDevicesMatchingStates()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getPanDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getConnectionState(BluetoothDevice device) {
+ if (DBG) log("getState(" + device + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mService.getPanDeviceConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ /**
+ * {@inheritDoc}
* @hide
*/
- public List<BluetoothDevice> getConnectedDevices() {
- if (DBG) log("getConnectedDevices");
- try {
- return mService.getConnectedPanDevices();
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return new ArrayList<BluetoothDevice>();
- }
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ // Priorities are not supported for PAN devices - since we don't
+ // auto connect.
+ return false;
}
- private static void log(String msg) {
- Log.d(TAG, msg);
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ public int getPriority(BluetoothDevice device) {
+ if (DBG) log("getPriority(" + device + ")");
+ // Priorities are not supported for PAN devices - since we don't
+ // auto connect.
+ return BluetoothProfile.PRIORITY_ON;
}
public void setBluetoothTethering(boolean value) {
+ if (DBG) log("setBluetoothTethering(" + value + ")");
try {
mService.setBluetoothTethering(value);
} catch (RemoteException e) {
- Log.e(TAG, "", e);
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
}
}
public boolean isTetheringOn() {
+ if (DBG) log("isTetheringOn()");
try {
return mService.isTetheringOn();
} catch (RemoteException e) {
- Log.e(TAG, "", e);
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
-}
+
+ private boolean isEnabled() {
+ if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ return false;
+ }
+
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+} \ No newline at end of file
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 1ffee7205395..1ad66f71b938 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -58,10 +58,12 @@ public interface BluetoothProfile {
* Headset and Handsfree profile
*/
public static final int HEADSET = 1;
+
/**
* A2DP profile.
*/
public static final int A2DP = 2;
+
/**
* Input Device Profile
* @hide
@@ -69,6 +71,12 @@ public interface BluetoothProfile {
public static final int INPUT_DEVICE = 3;
/**
+ * PAN Profile
+ * @hide
+ */
+ public static final int PAN = 4;
+
+ /**
* Default priority for devices that we try to auto-connect to and
* and allow incoming connections for the profile
* @hide
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index aa1adcbbc2a8..c08f14f3f81f 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -96,17 +96,32 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
public void startMonitoring(Context context, Handler target) {
mContext = context;
mCsHandler = target;
- mBluetoothPan = new BluetoothPan(mContext);
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter != null) {
+ adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
+ }
}
+ private BluetoothProfile.ServiceListener mProfileServiceListener =
+ new BluetoothProfile.ServiceListener() {
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ mBluetoothPan = (BluetoothPan) proxy;
+ }
+ public void onServiceDisconnected(int profile) {
+ mBluetoothPan = null;
+ }
+ };
+
/**
* Disable connectivity to a network
* TODO: do away with return value after making MobileDataStateTracker async
*/
public boolean teardown() {
mTeardownRequested.set(true);
- for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
- mBluetoothPan.disconnect(device);
+ if (mBluetoothPan != null) {
+ for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
+ mBluetoothPan.disconnect(device);
+ }
}
return true;
}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 69fb06a0f7b0..d25f5d0cb336 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -92,8 +92,9 @@ interface IBluetooth
boolean isTetheringOn();
void setBluetoothTethering(boolean value);
- int getPanDeviceState(in BluetoothDevice device);
+ int getPanDeviceConnectionState(in BluetoothDevice device);
List<BluetoothDevice> getConnectedPanDevices();
+ List<BluetoothDevice> getPanDevicesMatchingConnectionStates(in int[] states);
boolean connectPanDevice(in BluetoothDevice device);
boolean disconnectPanDevice(in BluetoothDevice device);
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index c2f3ae70b8b2..d8a5b45c9cda 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -508,23 +508,86 @@ public class Camera {
* finish processing the data in them.
*
* <p>The size of the buffer is determined by multiplying the preview
- * image width, height, and bytes per pixel. The width and height can be
- * read from {@link Camera.Parameters#getPreviewSize()}. Bytes per pixel
+ * image width, height, and bytes per pixel. The width and height can be
+ * read from {@link Camera.Parameters#getPreviewSize()}. Bytes per pixel
* can be computed from
* {@link android.graphics.ImageFormat#getBitsPerPixel(int)} / 8,
* using the image format from {@link Camera.Parameters#getPreviewFormat()}.
*
* <p>This method is only necessary when
- * {@link #setPreviewCallbackWithBuffer(PreviewCallback)} is used. When
+ * {@link #setPreviewCallbackWithBuffer(PreviewCallback)} is used. When
* {@link #setPreviewCallback(PreviewCallback)} or
* {@link #setOneShotPreviewCallback(PreviewCallback)} are used, buffers
- * are automatically allocated.
+ * are automatically allocated. When a supplied buffer is too small to
+ * hold the preview frame data, preview callback will return null and
+ * the buffer will be removed from the buffer queue.
*
* @param callbackBuffer the buffer to add to the queue.
* The size should be width * height * bits_per_pixel / 8.
* @see #setPreviewCallbackWithBuffer(PreviewCallback)
*/
- public native final void addCallbackBuffer(byte[] callbackBuffer);
+ public final void addCallbackBuffer(byte[] callbackBuffer)
+ {
+ _addCallbackBuffer(callbackBuffer, CAMERA_MSG_PREVIEW_FRAME);
+ }
+
+ /**
+ * Adds a pre-allocated buffer to the raw image callback buffer queue.
+ * Applications can add one or more buffers to the queue. When a raw image
+ * frame arrives and there is still at least one available buffer, the
+ * buffer will be used to hold the raw image data and removed from the
+ * queue. Then raw image callback is invoked with the buffer. If a raw
+ * image frame arrives but there is no buffer left, the frame is
+ * discarded. Applications should add buffers back when they finish
+ * processing the data in them by calling this method again in order
+ * to avoid running out of raw image callback buffers.
+ *
+ * <p>The size of the buffer is determined by multiplying the raw image
+ * width, height, and bytes per pixel. The width and height can be
+ * read from {@link Camera.Parameters#getPictureSize()}. Bytes per pixel
+ * can be computed from
+ * {@link android.graphics.ImageFormat#getBitsPerPixel(int)} / 8,
+ * using the image format from {@link Camera.Parameters#getPreviewFormat()}.
+ *
+ * <p>This method is only necessary when the PictureCallbck for raw image
+ * is used while calling {@link #takePicture(Camera.ShutterCallback,
+ * Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)}.
+ *
+ * Please note that by calling this method, the mode for application-managed
+ * callback buffers is triggered. If this method has never been called,
+ * null will be returned by the raw image callback since there is
+ * no image callback buffer available. Furthermore, When a supplied buffer
+ * is too small to hold the raw image data, raw image callback will return
+ * null and the buffer will be removed from the buffer queue.
+ *
+ * @param callbackBuffer the buffer to add to the raw image callback buffer
+ * queue. The size should be width * height * (bits per pixel) / 8. An
+ * null callbackBuffer will be ignored and won't be added to the queue.
+ *
+ * @see #takePicture(Camera.ShutterCallback,
+ * Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)}.
+ *
+ * {@hide}
+ */
+ public final void addRawImageCallbackBuffer(byte[] callbackBuffer)
+ {
+ addCallbackBuffer(callbackBuffer, CAMERA_MSG_RAW_IMAGE);
+ }
+
+ private final void addCallbackBuffer(byte[] callbackBuffer, int msgType)
+ {
+ // CAMERA_MSG_VIDEO_FRAME may be allowed in the future.
+ if (msgType != CAMERA_MSG_PREVIEW_FRAME &&
+ msgType != CAMERA_MSG_RAW_IMAGE) {
+ throw new IllegalArgumentException(
+ "Unsupported message type: " + msgType);
+ }
+
+ _addCallbackBuffer(callbackBuffer, msgType);
+ }
+
+ private native final void _addCallbackBuffer(
+ byte[] callbackBuffer, int msgType);
private class EventHandler extends Handler
{
@@ -735,7 +798,7 @@ public class Camera {
PictureCallback jpeg) {
takePicture(shutter, raw, null, jpeg);
}
- private native final void native_takePicture();
+ private native final void native_takePicture(int msgType);
/**
* Triggers an asynchronous image capture. The camera service will initiate
@@ -743,7 +806,8 @@ public class Camera {
* The shutter callback occurs after the image is captured. This can be used
* to trigger a sound to let the user know that image has been captured. The
* raw callback occurs when the raw image data is available (NOTE: the data
- * may be null if the hardware does not have enough memory to make a copy).
+ * will be null if there is no raw image callback buffer available or the
+ * raw image callback buffer is not large enough to hold the raw image).
* The postview callback occurs when a scaled, fully processed postview
* image is available (NOTE: not all hardware supports this). The jpeg
* callback occurs when the compressed image is available. If the
@@ -762,6 +826,8 @@ public class Camera {
* @param raw the callback for raw (uncompressed) image data, or null
* @param postview callback with postview image data, may be null
* @param jpeg the callback for JPEG image data, or null
+ *
+ * @see #addRawImageCallbackBuffer(byte[])
*/
public final void takePicture(ShutterCallback shutter, PictureCallback raw,
PictureCallback postview, PictureCallback jpeg) {
@@ -769,7 +835,23 @@ public class Camera {
mRawImageCallback = raw;
mPostviewCallback = postview;
mJpegCallback = jpeg;
- native_takePicture();
+
+ // If callback is not set, do not send me callbacks.
+ int msgType = 0;
+ if (mShutterCallback != null) {
+ msgType |= CAMERA_MSG_SHUTTER;
+ }
+ if (mRawImageCallback != null) {
+ msgType |= CAMERA_MSG_RAW_IMAGE;
+ }
+ if (mPostviewCallback != null) {
+ msgType |= CAMERA_MSG_POSTVIEW_FRAME;
+ }
+ if (mJpegCallback != null) {
+ msgType |= CAMERA_MSG_COMPRESSED_IMAGE;
+ }
+
+ native_takePicture(msgType);
}
/**
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 8c55bf33788b..78d7991796b9 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -122,13 +122,13 @@ public class SensorEvent {
*
* final float alpha = 0.8;
*
- * gravity[0] = alpha * gravity[0] + (1 - alpha) * event.data[0];
- * gravity[1] = alpha * gravity[1] + (1 - alpha) * event.data[1];
- * gravity[2] = alpha * gravity[2] + (1 - alpha) * event.data[2];
+ * gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
+ * gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
+ * gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
*
- * linear_acceleration[0] = event.data[0] - gravity[0];
- * linear_acceleration[1] = event.data[1] - gravity[1];
- * linear_acceleration[2] = event.data[2] - gravity[2];
+ * linear_acceleration[0] = event.values[0] - gravity[0];
+ * linear_acceleration[1] = event.values[1] - gravity[1];
+ * linear_acceleration[2] = event.values[2] - gravity[2];
* }
* </pre>
*
@@ -186,9 +186,9 @@ public class SensorEvent {
* {
* if (timestamp != 0) {
* final float dT = (event.timestamp - timestamp) * NS2S;
- * angle[0] += event.data[0] * dT;
- * angle[1] += event.data[1] * dT;
- * angle[2] += event.data[2] * dT;
+ * angle[0] += event.values[0] * dT;
+ * angle[1] += event.values[1] * dT;
+ * angle[2] += event.values[2] * dT;
* }
* timestamp = event.timestamp;
* }
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 3bfd005d2058..57ee440755cd 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -139,8 +139,6 @@ public class Browser {
public static final int SEARCHES_PROJECTION_SEARCH_INDEX = 1;
public static final int SEARCHES_PROJECTION_DATE_INDEX = 2;
- private static final String SEARCHES_WHERE_CLAUSE = "search = ?";
-
/* Set a cap on the count of history items in the history/bookmark
table, to prevent db and layout operations from dragging to a
crawl. Revisit this cap when/if db/layout performance
@@ -167,6 +165,13 @@ public class Browser {
}
/**
+ * Passed along with an Intent to a browser, specifying that a new tab
+ * be created. Overrides EXTRA_APPLICATION_ID; if both are set, a new tab
+ * will be used, rather than using the same one.
+ */
+ public static final String EXTRA_CREATE_NEW_TAB = "create_new_tab";
+
+ /**
* Stores a Bitmap extra in an {@link Intent} representing the screenshot of
* a page to share. When receiving an {@link Intent#ACTION_SEND} from the
* Browser, use this to access the screenshot.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b05b078a27d0..4f88612f0e39 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -862,8 +862,9 @@ public final class ContactsContract {
}
/**
- * Types of data used to produce the display name for a contact. Listed in the order
- * of increasing priority.
+ * Types of data used to produce the display name for a contact. In the order
+ * of increasing priority: {@link #EMAIL}, {@link #PHONE},
+ * {@link #ORGANIZATION}, {@link #NICKNAME}, {@link #STRUCTURED_NAME}.
*/
public interface DisplayNameSources {
public static final int UNDEFINED = 0;
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index c0b3cc8fb523..578580a180b1 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -785,7 +785,7 @@ class BluetoothEventLoop {
boolean connected = false;
BluetoothDevice device = mAdapter.getRemoteDevice(address);
- int state = mBluetoothService.getPanDeviceState(device);
+ int state = mBluetoothService.getPanDeviceConnectionState(device);
if (state == BluetoothPan.STATE_CONNECTING) {
if (result == BluetoothPan.PAN_CONNECT_FAILED_ALREADY_CONNECTED) {
connected = true;
diff --git a/core/java/android/server/BluetoothPanProfileHandler.java b/core/java/android/server/BluetoothPanProfileHandler.java
index fb964396e4fc..3f24811e2805 100644
--- a/core/java/android/server/BluetoothPanProfileHandler.java
+++ b/core/java/android/server/BluetoothPanProfileHandler.java
@@ -58,6 +58,9 @@ final class BluetoothPanProfileHandler {
private Context mContext;
private BluetoothService mBluetoothService;
+ static final String NAP_ROLE = "nap";
+ static final String NAP_BRIDGE = "pan1";
+
private BluetoothPanProfileHandler(Context context, BluetoothService service) {
mContext = context;
mPanDevices = new HashMap<BluetoothDevice, BluetoothPanDevice>();
@@ -114,7 +117,7 @@ final class BluetoothPanProfileHandler {
}
}
- synchronized int getPanDeviceState(BluetoothDevice device) {
+ synchronized int getPanDeviceConnectionState(BluetoothDevice device) {
BluetoothPanDevice panDevice = mPanDevices.get(device);
if (panDevice == null) {
return BluetoothPan.STATE_DISCONNECTED;
@@ -125,13 +128,13 @@ final class BluetoothPanProfileHandler {
synchronized boolean connectPanDevice(BluetoothDevice device) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
if (DBG) Log.d(TAG, "connect PAN(" + objectPath + ")");
- if (getPanDeviceState(device) != BluetoothPan.STATE_DISCONNECTED) {
+ if (getPanDeviceConnectionState(device) != BluetoothPan.STATE_DISCONNECTED) {
errorLog(device + " already connected to PAN");
}
int connectedCount = 0;
for (BluetoothDevice panDevice: mPanDevices.keySet()) {
- if (getPanDeviceState(panDevice) == BluetoothPan.STATE_CONNECTED) {
+ if (getPanDeviceConnectionState(panDevice) == BluetoothPan.STATE_CONNECTED) {
connectedCount ++;
}
}
@@ -187,18 +190,33 @@ final class BluetoothPanProfileHandler {
List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
for (BluetoothDevice device: mPanDevices.keySet()) {
- if (getPanDeviceState(device) == BluetoothPan.STATE_CONNECTED) {
+ if (getPanDeviceConnectionState(device) == BluetoothPan.STATE_CONNECTED) {
devices.add(device);
}
}
return devices;
}
+ synchronized List<BluetoothDevice> getPanDevicesMatchingConnectionStates(int[] states) {
+ List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
+
+ for (BluetoothDevice device: mPanDevices.keySet()) {
+ int panDeviceState = getPanDeviceConnectionState(device);
+ for (int state : states) {
+ if (state == panDeviceState) {
+ devices.add(device);
+ break;
+ }
+ }
+ }
+ return devices;
+ }
+
synchronized boolean disconnectPanDevice(BluetoothDevice device) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
debugLog("disconnect PAN(" + objectPath + ")");
- int state = getPanDeviceState(device);
+ int state = getPanDeviceConnectionState(device);
if (state != BluetoothPan.STATE_CONNECTED) {
debugLog(device + " already disconnected from PAN");
return false;
@@ -274,14 +292,10 @@ final class BluetoothPanProfileHandler {
panDevice.mLocalRole = role;
}
- if (state == BluetoothPan.STATE_DISCONNECTED) {
- mPanDevices.remove(device);
- }
-
- Intent intent = new Intent(BluetoothPan.ACTION_PAN_STATE_CHANGED);
+ Intent intent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
- intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, prevState);
- intent.putExtra(BluetoothPan.EXTRA_PAN_STATE, state);
+ intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_STATE, prevState);
+ intent.putExtra(BluetoothPan.EXTRA_STATE, state);
intent.putExtra(BluetoothPan.EXTRA_LOCAL_ROLE, role);
mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 70aaf0a009f1..ebe3ef284029 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -85,6 +85,7 @@ public class BluetoothService extends IBluetooth.Stub {
private BluetoothEventLoop mEventLoop;
private BluetoothHeadset mBluetoothHeadset;
private BluetoothInputDevice mInputDevice;
+ private BluetoothPan mPan;
private boolean mIsAirplaneSensitive;
private boolean mIsAirplaneToggleable;
private int mBluetoothState;
@@ -357,7 +358,8 @@ public class BluetoothService extends IBluetooth.Stub {
setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF);
if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles);
- setBluetoothTetheringNative(false, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE);
+ setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE,
+ BluetoothPanProfileHandler.NAP_BRIDGE);
// Allow 3 seconds for profiles to gracefully disconnect
// TODO: Introduce a callback mechanism so that each profile can notify
@@ -606,7 +608,8 @@ public class BluetoothService extends IBluetooth.Stub {
addReservedSdpRecords(uuids);
// Enable profiles maintained by Bluez userspace.
- setBluetoothTetheringNative(true, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE);
+ setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE,
+ BluetoothPanProfileHandler.NAP_BRIDGE);
// Add SDP records for profiles maintained by Bluez userspace
uuids.add(BluetoothUuid.AudioSource);
@@ -2082,6 +2085,8 @@ public class BluetoothService extends IBluetooth.Stub {
mBluetoothProfileServiceListener, BluetoothProfile.HEADSET);
mAdapter.getProfileProxy(mContext,
mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
+ mAdapter.getProfileProxy(mContext,
+ mBluetoothProfileServiceListener, BluetoothProfile.PAN);
pw.println("\n--Known devices--");
for (String address : mDeviceProperties.keySet()) {
@@ -2125,6 +2130,7 @@ public class BluetoothService extends IBluetooth.Stub {
dumpHeadsetProfile(pw);
dumpInputDeviceProfile(pw);
+ dumpPanProfile(pw);
pw.println("\n--Application Service Records--");
for (Integer handle : mServiceRecordToPid.keySet()) {
@@ -2138,10 +2144,10 @@ public class BluetoothService extends IBluetooth.Stub {
if (mBluetoothHeadset != null) {
List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
if (deviceList.size() == 0) {
- pw.println("\n--No headsets connected--");
+ pw.println("No headsets connected");
} else {
BluetoothDevice device = deviceList.get(0);
- pw.println("\ngetConnectedDevices[0] = " + device);
+ pw.println("getConnectedDevices[0] = " + device);
switch (mBluetoothHeadset.getConnectionState(device)) {
case BluetoothHeadset.STATE_CONNECTING:
@@ -2164,7 +2170,7 @@ public class BluetoothService extends IBluetooth.Stub {
deviceList.clear();
deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] {
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
- pw.println("\n--Connected and Disconnected Headsets");
+ pw.println("--Connected and Disconnected Headsets");
for (BluetoothDevice device: deviceList) {
pw.println(device);
if (mBluetoothHeadset.isAudioConnected(device)) {
@@ -2180,9 +2186,9 @@ public class BluetoothService extends IBluetooth.Stub {
if (mInputDevice != null) {
List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices();
if (deviceList.size() == 0) {
- pw.println("\nNo input devices connected--");
+ pw.println("No input devices connected");
} else {
- pw.println("\nNumber of connected devices:" + deviceList.size());
+ pw.println("Number of connected devices:" + deviceList.size());
BluetoothDevice device = deviceList.get(0);
pw.println("getConnectedDevices[0] = " + device);
pw.println("Priority of Connected device = " + mInputDevice.getPriority(device));
@@ -2210,6 +2216,41 @@ public class BluetoothService extends IBluetooth.Stub {
mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset);
}
+ private void dumpPanProfile(PrintWriter pw) {
+ pw.println("\n--Bluetooth Service- Pan Profile");
+ if (mPan != null) {
+ List<BluetoothDevice> deviceList = mPan.getConnectedDevices();
+ if (deviceList.size() == 0) {
+ pw.println("No Pan devices connected");
+ } else {
+ pw.println("Number of connected devices:" + deviceList.size());
+ BluetoothDevice device = deviceList.get(0);
+ pw.println("getConnectedDevices[0] = " + device);
+ pw.println("Priority of Connected device = " + mPan.getPriority(device));
+
+ switch (mPan.getConnectionState(device)) {
+ case BluetoothInputDevice.STATE_CONNECTING:
+ pw.println("getConnectionState() = STATE_CONNECTING");
+ break;
+ case BluetoothInputDevice.STATE_CONNECTED:
+ pw.println("getConnectionState() = STATE_CONNECTED");
+ break;
+ case BluetoothInputDevice.STATE_DISCONNECTING:
+ pw.println("getConnectionState() = STATE_DISCONNECTING");
+ break;
+ }
+ }
+ deviceList.clear();
+ deviceList = mPan.getDevicesMatchingConnectionStates(new int[] {
+ BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
+ pw.println("--Connected and Disconnected Pan devices");
+ for (BluetoothDevice device: deviceList) {
+ pw.println(device);
+ }
+ }
+ mAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothHeadset);
+ }
+
private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -2217,6 +2258,8 @@ public class BluetoothService extends IBluetooth.Stub {
mBluetoothHeadset = (BluetoothHeadset) proxy;
} else if (profile == BluetoothProfile.INPUT_DEVICE) {
mInputDevice = (BluetoothInputDevice) proxy;
+ } else if (profile == BluetoothProfile.PAN) {
+ mPan = (BluetoothPan) proxy;
}
}
public void onServiceDisconnected(int profile) {
@@ -2224,6 +2267,8 @@ public class BluetoothService extends IBluetooth.Stub {
mBluetoothHeadset = null;
} else if (profile == BluetoothProfile.INPUT_DEVICE) {
mInputDevice = null;
+ } else if (profile == BluetoothProfile.PAN) {
+ mPan = null;
}
}
};
@@ -2302,9 +2347,9 @@ public class BluetoothService extends IBluetooth.Stub {
mBluetoothPanProfileHandler.setBluetoothTethering(value);
}
- public synchronized int getPanDeviceState(BluetoothDevice device) {
+ public synchronized int getPanDeviceConnectionState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothPanProfileHandler.getPanDeviceState(device);
+ return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device);
}
public synchronized boolean connectPanDevice(BluetoothDevice device) {
@@ -2318,6 +2363,12 @@ public class BluetoothService extends IBluetooth.Stub {
return mBluetoothPanProfileHandler.getConnectedPanDevices();
}
+ public synchronized List<BluetoothDevice> getPanDevicesMatchingConnectionStates(
+ int[] states) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states);
+ }
+
public synchronized boolean disconnectPanDevice(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
diff --git a/core/java/android/webkit/SelectActionModeCallback.java b/core/java/android/webkit/SelectActionModeCallback.java
index ea09fc0c0ed0..104deb1c82f0 100644
--- a/core/java/android/webkit/SelectActionModeCallback.java
+++ b/core/java/android/webkit/SelectActionModeCallback.java
@@ -83,6 +83,7 @@ class SelectActionModeCallback implements ActionMode.Callback {
case com.android.internal.R.id.websearch:
mode.finish();
Intent i = new Intent(Intent.ACTION_WEB_SEARCH);
+ i.putExtra(SearchManager.EXTRA_NEW_SEARCH, true);
i.putExtra(SearchManager.QUERY, mWebView.getSelection());
mWebView.getContext().startActivity(i);
break;
diff --git a/core/java/android/widget/ListAdapter.java b/core/java/android/widget/ListAdapter.java
index 0fd2e7090b46..d8fd1c987bff 100644
--- a/core/java/android/widget/ListAdapter.java
+++ b/core/java/android/widget/ListAdapter.java
@@ -26,10 +26,14 @@ package android.widget;
public interface ListAdapter extends Adapter {
/**
- * Are all items in this ListAdapter enabled?
- * If yes it means all items are selectable and clickable.
+ * Indicates whether all the items in this adapter are enabled. If the
+ * value returned by this method changes over time, there is no guarantee
+ * it will take effect. If true, it means all items are selectable and
+ * clickable (there is no separator.)
*
- * @return True if all items are enabled
+ * @return True if all items are enabled, false otherwise.
+ *
+ * @see #isEnabled(int)
*/
public boolean areAllItemsEnabled();
@@ -41,7 +45,10 @@ public interface ListAdapter extends Adapter {
* should be thrown in that case for fast failure.
*
* @param position Index of the item
+ *
* @return True if the item is not a separator
+ *
+ * @see #areAllItemsEnabled()
*/
boolean isEnabled(int position);
}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 9f70509f43c0..bfbfd374bbe7 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -53,25 +53,48 @@ public:
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr);
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
- void addCallbackBuffer(JNIEnv *env, jbyteArray cbb);
+ void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType);
void setCallbackMode(JNIEnv *env, bool installed, bool manualMode);
sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; }
+ bool isRawImageCallbackBufferAvailable() const;
void release();
private:
void copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType);
+ void clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers);
void clearCallbackBuffers_l(JNIEnv *env);
+ jbyteArray getCallbackBuffer(JNIEnv *env, Vector<jbyteArray> *buffers, size_t bufferSize);
jobject mCameraJObjectWeak; // weak reference to java object
jclass mCameraJClass; // strong reference to java class
sp<Camera> mCamera; // strong reference to native object
Mutex mLock;
+ /*
+ * Global reference application-managed raw image buffer queue.
+ *
+ * Manual-only mode is supported for raw image callbacks, which is
+ * set whenever method addCallbackBuffer() with msgType =
+ * CAMERA_MSG_RAW_IMAGE is called; otherwise, null is returned
+ * with raw image callbacks.
+ */
+ Vector<jbyteArray> mRawImageCallbackBuffers;
+
+ /*
+ * Application-managed preview buffer queue and the flags
+ * associated with the usage of the preview buffer callback.
+ */
Vector<jbyteArray> mCallbackBuffers; // Global reference application managed byte[]
bool mManualBufferMode; // Whether to use application managed buffers.
- bool mManualCameraCallbackSet; // Whether the callback has been set, used to reduce unnecessary calls to set the callback.
+ bool mManualCameraCallbackSet; // Whether the callback has been set, used to
+ // reduce unnecessary calls to set the callback.
};
+bool JNICameraContext::isRawImageCallbackBufferAvailable() const
+{
+ return !mRawImageCallbackBuffers.isEmpty();
+}
+
sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext)
{
sp<Camera> camera;
@@ -128,10 +151,48 @@ void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2)
return;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ /*
+ * If the notification or msgType is CAMERA_MSG_RAW_IMAGE_NOTIFY, change it
+ * to CAMERA_MSG_RAW_IMAGE since CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed
+ * to the Java app.
+ */
+ if (msgType == CAMERA_MSG_RAW_IMAGE_NOTIFY) {
+ msgType = CAMERA_MSG_RAW_IMAGE;
+ }
+
env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
mCameraJObjectWeak, msgType, ext1, ext2, NULL);
}
+jbyteArray JNICameraContext::getCallbackBuffer(
+ JNIEnv* env, Vector<jbyteArray>* buffers, size_t bufferSize)
+{
+ jbyteArray obj = NULL;
+
+ // Vector access should be protected by lock in postData()
+ if (!buffers->isEmpty()) {
+ LOGV("Using callback buffer from queue of length %d", buffers->size());
+ jbyteArray globalBuffer = buffers->itemAt(0);
+ buffers->removeAt(0);
+
+ obj = (jbyteArray)env->NewLocalRef(globalBuffer);
+ env->DeleteGlobalRef(globalBuffer);
+
+ if (obj != NULL) {
+ jsize bufferLength = env->GetArrayLength(obj);
+ if ((int)bufferLength < (int)bufferSize) {
+ LOGE("Callback buffer was too small! Expected %d bytes, but got %d bytes!",
+ bufferSize, bufferLength);
+ env->DeleteLocalRef(obj);
+ return NULL;
+ }
+ }
+ }
+
+ return obj;
+}
+
void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType)
{
jbyteArray obj = NULL;
@@ -141,7 +202,7 @@ void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int
ssize_t offset;
size_t size;
sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
- LOGV("postData: off=%d, size=%d", offset, size);
+ LOGV("copyAndPost: off=%ld, size=%d", offset, size);
uint8_t *heapBase = (uint8_t*)heap->base();
if (heapBase != NULL) {
@@ -151,32 +212,28 @@ void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int
LOGV("Allocating callback buffer");
obj = env->NewByteArray(size);
} else {
- // Vector access should be protected by lock in postData()
- if(!mCallbackBuffers.isEmpty()) {
- LOGV("Using callback buffer from queue of length %d", mCallbackBuffers.size());
- jbyteArray globalBuffer = mCallbackBuffers.itemAt(0);
- mCallbackBuffers.removeAt(0);
-
- obj = (jbyteArray)env->NewLocalRef(globalBuffer);
- env->DeleteGlobalRef(globalBuffer);
-
- if (obj != NULL) {
- jsize bufferLength = env->GetArrayLength(obj);
- if ((int)bufferLength < (int)size) {
- LOGE("Manually set buffer was too small! Expected %d bytes, but got %d!",
- size, bufferLength);
- env->DeleteLocalRef(obj);
- return;
+ switch (msgType) {
+ case CAMERA_MSG_PREVIEW_FRAME: {
+ obj = getCallbackBuffer(env, &mCallbackBuffers, size);
+
+ if (mCallbackBuffers.isEmpty()) {
+ LOGV("Out of buffers, clearing callback!");
+ mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
+ mManualCameraCallbackSet = false;
+
+ if (obj == NULL) {
+ return;
+ }
}
+ break;
}
- }
-
- if(mCallbackBuffers.isEmpty()) {
- LOGV("Out of buffers, clearing callback!");
- mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
- mManualCameraCallbackSet = false;
-
- if (obj == NULL) {
+ case CAMERA_MSG_RAW_IMAGE: {
+ obj = getCallbackBuffer(env, &mRawImageCallbackBuffers, size);
+ break;
+ }
+ default: {
+ jniThrowException(env,
+ "java/lang/RuntimeException", "Unsupported message type");
return;
}
}
@@ -212,21 +269,27 @@ void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr)
}
// return data based on callback type
- switch(msgType) {
- case CAMERA_MSG_VIDEO_FRAME:
- // should never happen
- break;
- // don't return raw data to Java
- case CAMERA_MSG_RAW_IMAGE:
- LOGV("rawCallback");
- env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
- mCameraJObjectWeak, msgType, 0, 0, NULL);
- break;
- default:
- // TODO: Change to LOGV
- LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
- copyAndPost(env, dataPtr, msgType);
- break;
+ switch (msgType) {
+ case CAMERA_MSG_VIDEO_FRAME:
+ // should never happen
+ break;
+
+ // For backward-compatibility purpose, if there is no callback
+ // buffer for raw image, the callback returns null.
+ case CAMERA_MSG_RAW_IMAGE:
+ LOGV("rawCallback");
+ if (mRawImageCallbackBuffers.isEmpty()) {
+ env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+ mCameraJObjectWeak, msgType, 0, 0, NULL);
+ } else {
+ copyAndPost(env, dataPtr, msgType);
+ }
+ break;
+
+ default:
+ LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
+ copyAndPost(env, dataPtr, msgType);
+ break;
}
}
@@ -251,7 +314,7 @@ void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualM
if (!installed) {
mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
- clearCallbackBuffers_l(env);
+ clearCallbackBuffers_l(env, &mCallbackBuffers);
} else if (mManualBufferMode) {
if (!mCallbackBuffers.isEmpty()) {
mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_CAMERA);
@@ -259,24 +322,44 @@ void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualM
}
} else {
mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_BARCODE_SCANNER);
- clearCallbackBuffers_l(env);
+ clearCallbackBuffers_l(env, &mCallbackBuffers);
}
}
-void JNICameraContext::addCallbackBuffer(JNIEnv *env, jbyteArray cbb)
+void JNICameraContext::addCallbackBuffer(
+ JNIEnv *env, jbyteArray cbb, int msgType)
{
+ LOGV("addCallbackBuffer: 0x%x", msgType);
if (cbb != NULL) {
Mutex::Autolock _l(mLock);
- jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
- mCallbackBuffers.push(cbb);
-
- LOGV("Adding callback buffer to queue, %d total", mCallbackBuffers.size());
-
- // We want to make sure the camera knows we're ready for the next frame.
- // This may have come unset had we not had a callbackbuffer ready for it last time.
- if (mManualBufferMode && !mManualCameraCallbackSet) {
- mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_CAMERA);
- mManualCameraCallbackSet = true;
+ switch (msgType) {
+ case CAMERA_MSG_PREVIEW_FRAME: {
+ jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
+ mCallbackBuffers.push(callbackBuffer);
+
+ LOGV("Adding callback buffer to queue, %d total",
+ mCallbackBuffers.size());
+
+ // We want to make sure the camera knows we're ready for the
+ // next frame. This may have come unset had we not had a
+ // callbackbuffer ready for it last time.
+ if (mManualBufferMode && !mManualCameraCallbackSet) {
+ mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_CAMERA);
+ mManualCameraCallbackSet = true;
+ }
+ break;
+ }
+ case CAMERA_MSG_RAW_IMAGE: {
+ jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
+ mRawImageCallbackBuffers.push(callbackBuffer);
+ break;
+ }
+ default: {
+ jniThrowException(env,
+ "java/lang/IllegalArgumentException",
+ "Unsupported message type");
+ return;
+ }
}
} else {
LOGE("Null byte array!");
@@ -285,10 +368,15 @@ void JNICameraContext::addCallbackBuffer(JNIEnv *env, jbyteArray cbb)
void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env)
{
- LOGV("Clearing callback buffers, %d remained", mCallbackBuffers.size());
- while(!mCallbackBuffers.isEmpty()) {
- env->DeleteGlobalRef(mCallbackBuffers.top());
- mCallbackBuffers.pop();
+ clearCallbackBuffers_l(env, &mCallbackBuffers);
+ clearCallbackBuffers_l(env, &mRawImageCallbackBuffers);
+}
+
+void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers) {
+ LOGV("Clearing callback buffers, %d remained", buffers->size());
+ while (!buffers->isEmpty()) {
+ env->DeleteGlobalRef(buffers->top());
+ buffers->pop();
}
}
@@ -458,13 +546,13 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t
context->setCallbackMode(env, installed, manualBuffer);
}
-static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes) {
- LOGV("addCallbackBuffer");
+static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) {
+ LOGV("addCallbackBuffer: 0x%x", msgType);
JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
if (context != NULL) {
- context->addCallbackBuffer(env, bytes);
+ context->addCallbackBuffer(env, bytes, msgType);
}
}
@@ -492,14 +580,32 @@ static void android_hardware_Camera_cancelAutoFocus(JNIEnv *env, jobject thiz)
}
}
-static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz)
+static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, int msgType)
{
LOGV("takePicture");
JNICameraContext* context;
sp<Camera> camera = get_native_camera(env, thiz, &context);
if (camera == 0) return;
- if (camera->takePicture() != NO_ERROR) {
+ /*
+ * When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback
+ * buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the
+ * notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY
+ * is enabled to receive the callback notification but no data.
+ *
+ * Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the
+ * Java application.
+ */
+ if (msgType & CAMERA_MSG_RAW_IMAGE) {
+ LOGV("Enable raw image callback buffer");
+ if (!context->isRawImageCallbackBufferAvailable()) {
+ LOGV("Enable raw image notification, since no callback buffer exists");
+ msgType &= ~CAMERA_MSG_RAW_IMAGE;
+ msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY;
+ }
+ }
+
+ if (camera->takePicture(msgType) != NO_ERROR) {
jniThrowException(env, "java/lang/RuntimeException", "takePicture failed");
return;
}
@@ -638,8 +744,8 @@ static JNINativeMethod camMethods[] = {
{ "setHasPreviewCallback",
"(ZZ)V",
(void *)android_hardware_Camera_setHasPreviewCallback },
- { "addCallbackBuffer",
- "([B)V",
+ { "_addCallbackBuffer",
+ "([BI)V",
(void *)android_hardware_Camera_addCallbackBuffer },
{ "native_autoFocus",
"()V",
@@ -648,7 +754,7 @@ static JNINativeMethod camMethods[] = {
"()V",
(void *)android_hardware_Camera_cancelAutoFocus },
{ "native_takePicture",
- "()V",
+ "(I)V",
(void *)android_hardware_Camera_takePicture },
{ "native_setParameters",
"(Ljava/lang/String;)V",
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index fc806a502f15..667ba75ebd46 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -556,6 +556,18 @@ static jboolean android_net_wifi_setSuspendOptimizationsCommand(JNIEnv* env, job
return doBooleanCommand(cmdstr, "OK");
}
+static void android_net_wifi_enableBackgroundScan(JNIEnv* env, jobject clazz, jboolean enable)
+{
+ //Note: BGSCAN-START and BGSCAN-STOP are documented in core/res/res/values/config.xml
+ //and will need an update if the names are changed
+ if (enable) {
+ doBooleanCommand("DRIVER BGSCAN-START", "OK");
+ }
+ else {
+ doBooleanCommand("DRIVER BGSCAN-STOP", "OK");
+ }
+}
+
// ----------------------------------------------------------------------------
/*
@@ -623,6 +635,7 @@ static JNINativeMethod gWifiMethods[] = {
(void*) android_net_wifi_setSuspendOptimizationsCommand},
{ "setCountryCodeCommand", "(Ljava/lang/String;)Z",
(void*) android_net_wifi_setCountryCodeCommand},
+ { "enableBackgroundScan", "(Z)V", (void*) android_net_wifi_enableBackgroundScan},
};
int register_android_net_wifi_WifiManager(JNIEnv* env)
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d9eccd6f2729..b48adf136286 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3176,7 +3176,10 @@
<attr name="visible" format="boolean" />
</declare-styleable>
+ <!-- Drawable used to render several states. Each state is represented by
+ a child drawable. -->
<declare-styleable name="StateListDrawable">
+ <!-- Indicates whether the drawable should be initially visible. -->
<attr name="visible" />
<!-- If true, allows the drawable's padding to change based on the
current state that is selected. If false, the padding will
@@ -3200,6 +3203,7 @@
<attr name="exitFadeDuration" format="integer" />
</declare-styleable>
+ <!-- Drawable used to render several animated frames. -->
<declare-styleable name="AnimationDrawable">
<attr name="visible" />
<attr name="variablePadding" />
@@ -3209,6 +3213,7 @@
<attr name="oneshot" format="boolean" />
</declare-styleable>
+ <!-- Represents a single frame inside an AnimationDrawable. -->
<declare-styleable name="AnimationDrawableItem">
<!-- Amount of time (in milliseconds) to display this frame. -->
<attr name="duration" format="integer" />
@@ -3217,12 +3222,21 @@
<attr name="drawable" format="reference" />
</declare-styleable>
+ <!-- Drawable used to render a geometric shape, with a gradient or a solid color. -->
<declare-styleable name="GradientDrawable">
+ <!-- Indicates whether the drawable should intially be visible. -->
<attr name="visible" />
+ <!-- Enables or disables dithering. -->
+ <attr name="dither" />
+ <!-- Indicates what shape to fill with a gradient. -->
<attr name="shape">
+ <!-- Rectangle shape, with optional rounder corners. -->
<enum name="rectangle" value="0" />
+ <!-- Oval shape. -->
<enum name="oval" value="1" />
+ <!-- Line shape. -->
<enum name="line" value="2" />
+ <!-- Ring shape. -->
<enum name="ring" value="3" />
</attr>
<!-- Inner radius of the ring expressed as a ratio of the ring's width. For instance,
@@ -3237,71 +3251,123 @@
<attr name="innerRadius" format="dimension" />
<!-- Thickness of the ring. When defined, thicknessRatio is ignored. -->
<attr name="thickness" format="dimension" />
+ <!-- Indicates whether the drawable's level affects the way the gradient is drawn. -->
<attr name="useLevel" />
</declare-styleable>
+ <!-- Used to specify the size of the shape for GradientDrawable. -->
<declare-styleable name="GradientDrawableSize">
+ <!-- Width of the gradient shape. -->
<attr name="width" />
+ <!-- Height of the gradient shape. -->
<attr name="height" />
</declare-styleable>
+ <!-- Used to describe the gradient used to fill the shape of a GradientDrawable. -->
<declare-styleable name="GradientDrawableGradient">
+ <!-- Start color of the gradient. -->
<attr name="startColor" format="color" />
- <!-- Optional center color. For linear gradients, use centerX or centerY to place the center color. -->
+ <!-- Optional center color. For linear gradients, use centerX or centerY
+ to place the center color. -->
<attr name="centerColor" format="color" />
+ <!-- End color of the gradient. -->
<attr name="endColor" format="color" />
<attr name="useLevel" format="boolean" />
+ <!-- Angle of the gradient. -->
<attr name="angle" format="float" />
+ <!-- Type of gradient. The default type is linear. -->
<attr name="type">
+ <!-- Linear gradient. -->
<enum name="linear" value="0" />
+ <!-- Radial, or circular, gradient. -->
<enum name="radial" value="1" />
+ <!-- Sweep, or angled or diamond, gradient. -->
<enum name="sweep" value="2" />
</attr>
+ <!-- X coordinate of the origin of the gradient within the shape. -->
<attr name="centerX" format="float|fraction" />
+ <!-- Y coordinate of the origin of the gradient within the shape. -->
<attr name="centerY" format="float|fraction" />
+ <!-- Radius of the gradient, used only with radial gradient. -->
<attr name="gradientRadius" format="float|fraction" />
</declare-styleable>
+ <!-- Used to fill the shape of GradientDrawable with a solid color. -->
<declare-styleable name="GradientDrawableSolid">
+ <!-- Solid color for the gradient shape. -->
<attr name="color" format="color" />
</declare-styleable>
+ <!-- Used to describe the optional stroke of a GradientDrawable. -->
<declare-styleable name="GradientDrawableStroke">
+ <!-- Width of the gradient shape's stroke. -->
<attr name="width" />
+ <!-- Color of the gradient shape's stroke. -->
<attr name="color" />
+ <!-- Length of a dash in the stroke. -->
<attr name="dashWidth" format="dimension" />
+ <!-- Gap between dashes in the stroke. -->
<attr name="dashGap" format="dimension" />
</declare-styleable>
+ <!-- Describes the corners for the rectangle shape of a GradientDrawable.
+ This can be used to render rounded corners. -->
<declare-styleable name="DrawableCorners">
+ <!-- Defines the radius of the four corners. -->
<attr name="radius" format="dimension" />
+ <!-- Radius of the top left corner. -->
<attr name="topLeftRadius" format="dimension" />
+ <!-- Radius of the top right corner. -->
<attr name="topRightRadius" format="dimension" />
+ <!-- Radius of the bottom left corner. -->
<attr name="bottomLeftRadius" format="dimension" />
+ <!-- Radius of the bottom right corner. -->
<attr name="bottomRightRadius" format="dimension" />
</declare-styleable>
+ <!-- Used to specify the optional padding of a GradientDrawable. -->
<declare-styleable name="GradientDrawablePadding">
+ <!-- Amount of left padding inside the gradient shape. -->
<attr name="left" format="dimension" />
+ <!-- Amount of top padding inside the gradient shape. -->
<attr name="top" format="dimension" />
+ <!-- Amount of right padding inside the gradient shape. -->
<attr name="right" format="dimension" />
+ <!-- Amount of bottom padding inside the gradient shape. -->
<attr name="bottom" format="dimension" />
</declare-styleable>
+ <!-- Drawable used to render several drawables stacked on top of each other.
+ Each child drawable can be controlled individually. -->
<declare-styleable name="LayerDrawable">
+ <!-- Indicates the opacity of the layer. This can be useful to allow the
+ system to enable drawing optimizations. The default value is
+ translucent. -->
<attr name="opacity">
+ <!-- Indicates that the layer is opaque and contains no transparent
+ nor translucent pixels. -->
<enum name="opaque" value="-1" />
+ <!-- The layer is completely transparent (no pixel will be drawn.) -->
<enum name="transparent" value="-2" />
+ <!-- The layer has translucent pixels. -->
<enum name="translucent" value="-3" />
</attr>
</declare-styleable>
+ <!-- Describes an item (or child) of a LayerDrawable. -->
<declare-styleable name="LayerDrawableItem">
+ <!-- Left coordinate of the layer. -->
<attr name="left" />
+ <!-- Top coordinate of the layer. -->
<attr name="top" />
+ <!-- Right coordinate of the layer. -->
<attr name="right" />
+ <!-- Bottom coordinate of the layer. -->
<attr name="bottom" />
+ <!-- Drawable used to render the layer. -->
<attr name="drawable" />
+ <!-- Identifier of the layer. This can be used to retrieve the layer
+ from a drawbable container. -->
<attr name="id" />
</declare-styleable>
@@ -3317,6 +3383,7 @@
<attr name="drawable" />
</declare-styleable>
+ <!-- Drawable used to rotate another drawable. -->
<declare-styleable name="RotateDrawable">
<attr name="visible" />
<attr name="fromDegrees" format="float" />
@@ -3475,6 +3542,8 @@
<attr name="width" />
<!-- Defines the height of the shape. -->
<attr name="height" />
+ <!-- Enables or disables dithering. -->
+ <attr name="dither" />
</declare-styleable>
<!-- ========================== -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0edd33e35c86..ce37943b492c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -194,6 +194,13 @@
<!-- Boolean indicating whether the wifi chipset has dual frequency band support -->
<bool translatable="false" name="config_wifi_dual_band_support">false</bool>
+ <!-- Boolean indicating whether the wifi chipset supports background scanning mechanism.
+ This mechanism allows the host to remain in suspend state and the dongle to actively
+ scan and wake the host when a configured SSID is detected by the dongle. This chipset
+ capability can provide power savings when wifi needs to be always kept on.
+ The driver commands needed to support the feature are BGSCAN-START and BGSCAN-STOP -->
+ <bool translatable="false" name="config_wifi_background_scan_support">false</bool>
+
<!-- Flag indicating whether the keyguard should be bypassed when
the slider is open. This can be set or unset depending how easily
the slider can be opened (for example, in a pocket or purse). -->
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index 1374e7f8afef..41104fe4ad72 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -108,15 +108,6 @@ public class WifiApStress
fail("thread in sleep is interrupted");
}
assertTrue("no uplink data connection after Wi-Fi tethering", mAct.pingTest(null));
- // Wait for 5 minutes, and verify the data connection again.
- // bug id: 3400027
- try {
- Thread.sleep(5 * 60 * 1000);
- } catch (Exception e) {
- fail("thread in sleep is interrupted");
- }
- // Verify the uplink data connection
- assertTrue("no uplink data connection", mAct.pingTest(null));
// Disable soft AP
assertTrue(mAct.mWifiManager.setWifiApEnabled(config, false));
// Wait for 30 seconds until Wi-Fi tethering is stopped
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index 35210e5c7b3d..85c5eaa85b9b 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.bluetooth.BluetoothPan;
+import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -296,8 +298,8 @@ public class BluetoothTestUtils extends Assert {
return;
}
- if (BluetoothPan.ACTION_PAN_STATE_CHANGED.equals(intent.getAction())) {
- int state = intent.getIntExtra(BluetoothPan.EXTRA_PAN_STATE, -1);
+ if (BluetoothPan.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
+ int state = intent.getIntExtra(BluetoothPan.EXTRA_STATE, -1);
assertNotSame(-1, state);
switch (state) {
case BluetoothPan.STATE_DISCONNECTED:
@@ -331,6 +333,9 @@ public class BluetoothTestUtils extends Assert {
case BluetoothProfile.INPUT_DEVICE:
mInput = (BluetoothInputDevice) proxy;
break;
+ case BluetoothProfile.PAN:
+ mPan = (BluetoothPan) proxy;
+ break;
}
}
}
@@ -347,6 +352,9 @@ public class BluetoothTestUtils extends Assert {
case BluetoothProfile.INPUT_DEVICE:
mInput = null;
break;
+ case BluetoothProfile.PAN:
+ mPan = null;
+ break;
}
}
}
@@ -362,6 +370,7 @@ public class BluetoothTestUtils extends Assert {
private BluetoothA2dp mA2dp;
private BluetoothHeadset mHeadset;
private BluetoothInputDevice mInput;
+ private BluetoothPan mPan;
/**
* Creates a utility instance for testing Bluetooth.
@@ -706,13 +715,13 @@ public class BluetoothTestUtils extends Assert {
* @param adapter The BT adapter.
*/
public void enablePan(BluetoothAdapter adapter) {
- BluetoothPan pan = new BluetoothPan(mContext);
- assertNotNull(pan);
+ if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
+ assertNotNull(mPan);
long start = System.currentTimeMillis();
- pan.setBluetoothTethering(true);
+ mPan.setBluetoothTethering(true);
long stop = System.currentTimeMillis();
- assertTrue(pan.isTetheringOn());
+ assertTrue(mPan.isTetheringOn());
writeOutput(String.format("enablePan() completed in %d ms", (stop - start)));
}
@@ -724,13 +733,13 @@ public class BluetoothTestUtils extends Assert {
* @param adapter The BT adapter.
*/
public void disablePan(BluetoothAdapter adapter) {
- BluetoothPan pan = new BluetoothPan(mContext);
- assertNotNull(pan);
+ if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
+ assertNotNull(mPan);
long start = System.currentTimeMillis();
- pan.setBluetoothTethering(false);
+ mPan.setBluetoothTethering(false);
long stop = System.currentTimeMillis();
- assertFalse(pan.isTetheringOn());
+ assertFalse(mPan.isTetheringOn());
writeOutput(String.format("disablePan() completed in %d ms", (stop - start)));
}
@@ -1102,11 +1111,11 @@ public class BluetoothTestUtils extends Assert {
fail(String.format("%s device not paired: device=%s", methodName, device));
}
- BluetoothPan pan = new BluetoothPan(mContext);
- assertNotNull(pan);
+ if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
+ assertNotNull(mPan);
ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
- int state = pan.getPanDeviceState(device);
+ int state = mPan.getConnectionState(device);
switch (state) {
case BluetoothPan.STATE_CONNECTED:
removeReceiver(receiver);
@@ -1119,7 +1128,7 @@ public class BluetoothTestUtils extends Assert {
start = System.currentTimeMillis();
if (role == BluetoothPan.LOCAL_PANU_ROLE) {
Log.i("BT", "connect to pan");
- assertTrue(pan.connect(device));
+ assertTrue(mPan.connect(device));
}
break;
default:
@@ -1130,7 +1139,7 @@ public class BluetoothTestUtils extends Assert {
long s = System.currentTimeMillis();
while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
- state = pan.getPanDeviceState(device);
+ state = mPan.getConnectionState(device);
if (state == BluetoothPan.STATE_CONNECTED
&& (receiver.getFiredFlags() & mask) == mask) {
long finish = receiver.getCompletedTime();
@@ -1209,23 +1218,23 @@ public class BluetoothTestUtils extends Assert {
fail(String.format("%s device not paired: device=%s", methodName, device));
}
- BluetoothPan pan = new BluetoothPan(mContext);
- assertNotNull(pan);
+ if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
+ assertNotNull(mPan);
ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
- int state = pan.getPanDeviceState(device);
+ int state = mPan.getConnectionState(device);
switch (state) {
- case BluetoothInputDevice.STATE_CONNECTED:
- case BluetoothInputDevice.STATE_CONNECTING:
+ case BluetoothPan.STATE_CONNECTED:
+ case BluetoothPan.STATE_CONNECTING:
start = System.currentTimeMillis();
if (role == BluetoothPan.LOCAL_PANU_ROLE) {
- assertTrue(pan.disconnect(device));
+ assertTrue(mPan.disconnect(device));
}
break;
- case BluetoothInputDevice.STATE_DISCONNECTED:
+ case BluetoothPan.STATE_DISCONNECTED:
removeReceiver(receiver);
return;
- case BluetoothInputDevice.STATE_DISCONNECTING:
+ case BluetoothPan.STATE_DISCONNECTING:
mask = 0; // Don't check for received intents since we might have missed them.
break;
default:
@@ -1236,7 +1245,7 @@ public class BluetoothTestUtils extends Assert {
long s = System.currentTimeMillis();
while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
- state = pan.getPanDeviceState(device);
+ state = mPan.getConnectionState(device);
if (state == BluetoothInputDevice.STATE_DISCONNECTED
&& (receiver.getFiredFlags() & mask) == mask) {
long finish = receiver.getCompletedTime();
@@ -1321,7 +1330,7 @@ public class BluetoothTestUtils extends Assert {
private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role,
int expectedFlags) {
- String[] actions = {BluetoothPan.ACTION_PAN_STATE_CHANGED};
+ String[] actions = {BluetoothPan.ACTION_CONNECTION_STATE_CHANGED};
ConnectPanReceiver receiver = new ConnectPanReceiver(device, role, expectedFlags);
addReceiver(receiver, actions);
return receiver;
@@ -1351,6 +1360,11 @@ public class BluetoothTestUtils extends Assert {
sleep(POLL_TIME);
}
return mInput;
+ case BluetoothProfile.PAN:
+ while (mPan == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+ sleep(POLL_TIME);
+ }
+ return mPan;
default:
return null;
}
diff --git a/docs/html/sdk/android-3.0.jd b/docs/html/sdk/android-3.0.jd
index 998c7c36b07a..6c087bb41b7c 100644
--- a/docs/html/sdk/android-3.0.jd
+++ b/docs/html/sdk/android-3.0.jd
@@ -868,8 +868,8 @@ dimensions.</p>
<h3>JSON utilities</h3>
<p>New classes, {@link android.util.JsonReader} and {@link android.util.JsonWriter}, help you
-read and write JSON streams. The new APIs compliment the {@link org.json} classes which manipulate a
-document in memory.</p>
+read and write JSON streams. The new APIs complement the {@link org.json} classes, which manipulate
+a document in memory.</p>
<p>You can create an instance of {@link android.util.JsonReader} by calling
its constructor method and passing the {@link java.io.InputStreamReader} that feeds the JSON string.
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index df8869e4b854..7f6f0105ad67 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -2,20 +2,20 @@ page.title=Android SDK
sdk.redirect=0
sdk.win_installer=installer_r10-windows.exe
-sdk.win_installer_bytes=32845713
-sdk.win_installer_checksum=4e4356c472a6271ac9c062df0219dcb3
+sdk.win_installer_bytes=32878481
+sdk.win_installer_checksum=8ffa2dd734829d0bbd3ea601b50b36c7
sdk.win_download=android-sdk_r10-windows.zip
-sdk.win_bytes=30112516
-sdk.win_checksum=643a75d99f5d4ca39dcf743fe894d599
+sdk.win_bytes=32832260
+sdk.win_checksum=1e42b8f528d9ca6d9b887c58c6f1b9a2
sdk.mac_download=android-sdk_r10-mac_x86.zip
-sdk.mac_bytes=28224540
-sdk.mac_checksum=4d0a99a458e4f4bde65a01f8545f27e9
+sdk.mac_bytes=28847132
+sdk.mac_checksum=e3aa5578a6553b69cc36659c9505be3f
sdk.linux_download=android-sdk_r10-linux_x86.tgz
-sdk.linux_bytes=26556013
-sdk.linux_checksum=10cafdd44771bfe2ba9d4440886389e7
+sdk.linux_bytes=26981997
+sdk.linux_checksum=c022dda3a56c8a67698e6a39b0b1a4e0
@jd:body
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index cffee5fd4e9c..8d1756152eca 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -240,7 +240,7 @@ public class BitmapFactory {
/**
* The resulting height of the bitmap, set independent of the state of
* inJustDecodeBounds. However, if there is an error trying to decode,
- * outHeight will be set to -1.
+ * outHeight will be set to -1.
*/
public int outHeight;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 65c6ccfa25d7..33f050c40028 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -624,6 +624,8 @@ public class GradientDrawable extends Drawable {
int shapeType = a.getInt(
com.android.internal.R.styleable.GradientDrawable_shape, RECTANGLE);
+ boolean dither = a.getBoolean(
+ com.android.internal.R.styleable.GradientDrawable_dither, false);
if (shapeType == RING) {
st.mInnerRadius = a.getDimensionPixelSize(
@@ -645,10 +647,11 @@ public class GradientDrawable extends Drawable {
a.recycle();
setShape(shapeType);
-
+ setDither(dither);
+
int type;
- final int innerDepth = parser.getDepth()+1;
+ final int innerDepth = parser.getDepth() + 1;
int depth;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth=parser.getDepth()) >= innerDepth
@@ -811,11 +814,12 @@ public class GradientDrawable extends Drawable {
com.android.internal.R.styleable.DrawableCorners_bottomRightRadius, radius);
if (topLeftRadius != radius || topRightRadius != radius ||
bottomLeftRadius != radius || bottomRightRadius != radius) {
+ // The corner radii are specified in clockwise order (see Path.addRoundRect())
setCornerRadii(new float[] {
topLeftRadius, topLeftRadius,
topRightRadius, topRightRadius,
- bottomLeftRadius, bottomLeftRadius,
- bottomRightRadius, bottomRightRadius
+ bottomRightRadius, bottomRightRadius,
+ bottomLeftRadius, bottomLeftRadius
});
}
a.recycle();
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index cb8774ddf874..4445b6a8636e 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -286,7 +286,7 @@ public class ShapeDrawable extends Drawable {
protected boolean inflateTag(String name, Resources r, XmlPullParser parser,
AttributeSet attrs) {
- if (name.equals("padding")) {
+ if ("padding".equals(name)) {
TypedArray a = r.obtainAttributes(attrs,
com.android.internal.R.styleable.ShapeDrawablePadding);
setPadding(
@@ -315,7 +315,10 @@ public class ShapeDrawable extends Drawable {
int color = mShapeState.mPaint.getColor();
color = a.getColor(com.android.internal.R.styleable.ShapeDrawable_color, color);
mShapeState.mPaint.setColor(color);
-
+
+ boolean dither = a.getBoolean(com.android.internal.R.styleable.ShapeDrawable_dither, false);
+ mShapeState.mPaint.setDither(dither);
+
setIntrinsicWidth((int)
a.getDimension(com.android.internal.R.styleable.ShapeDrawable_width, 0f));
setIntrinsicHeight((int)
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index e5f7e623c476..f3c8f64ad3de 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -66,16 +66,17 @@ namespace android {
// msgType in notifyCallback and dataCallback functions
enum {
- CAMERA_MSG_ERROR = 0x001,
- CAMERA_MSG_SHUTTER = 0x002,
- CAMERA_MSG_FOCUS = 0x004,
- CAMERA_MSG_ZOOM = 0x008,
- CAMERA_MSG_PREVIEW_FRAME = 0x010,
- CAMERA_MSG_VIDEO_FRAME = 0x020,
- CAMERA_MSG_POSTVIEW_FRAME = 0x040,
- CAMERA_MSG_RAW_IMAGE = 0x080,
- CAMERA_MSG_COMPRESSED_IMAGE = 0x100,
- CAMERA_MSG_ALL_MSGS = 0x1FF
+ CAMERA_MSG_ERROR = 0x0001,
+ CAMERA_MSG_SHUTTER = 0x0002,
+ CAMERA_MSG_FOCUS = 0x0004,
+ CAMERA_MSG_ZOOM = 0x0008,
+ CAMERA_MSG_PREVIEW_FRAME = 0x0010,
+ CAMERA_MSG_VIDEO_FRAME = 0x0020,
+ CAMERA_MSG_POSTVIEW_FRAME = 0x0040,
+ CAMERA_MSG_RAW_IMAGE = 0x0080,
+ CAMERA_MSG_COMPRESSED_IMAGE = 0x0100,
+ CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x0200,
+ CAMERA_MSG_ALL_MSGS = 0xFFFF
};
// cmdType in sendCommand functions
@@ -207,7 +208,7 @@ public:
status_t cancelAutoFocus();
// take a picture - picture returned from callback
- status_t takePicture();
+ status_t takePicture(int msgType);
// set preview/capture parameters - key/value pairs
status_t setParameters(const String8& params);
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index b2310a64c7d7..2344b3f3f423 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -70,7 +70,7 @@ public:
virtual status_t startRecording() = 0;
// stop recording mode
- virtual void stopRecording() = 0;
+ virtual void stopRecording() = 0;
// get recording state
virtual bool recordingEnabled() = 0;
@@ -84,8 +84,14 @@ public:
// cancel auto focus
virtual status_t cancelAutoFocus() = 0;
- // take a picture
- virtual status_t takePicture() = 0;
+ /*
+ * take a picture.
+ * @param msgType the message type an application selectively turn on/off
+ * on a photo-by-photo basis. The supported message types are:
+ * CAMERA_MSG_SHUTTER, CAMERA_MSG_RAW_IMAGE, CAMERA_MSG_COMPRESSED_IMAGE,
+ * and CAMERA_MSG_POSTVIEW_FRAME. Any other message types will be ignored.
+ */
+ virtual status_t takePicture(int msgType) = 0;
// set preview/capture parameters - key/value pairs
virtual status_t setParameters(const String8& params) = 0;
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 0bfb166a464d..cce9129c0f80 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -54,6 +54,22 @@ public:
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp<IOMX> getOMX() = 0;
+
+ // codecs usage tracking for the battery app
+ enum BatteryDataBits {
+ // tracking audio codec
+ kBatteryDataTrackAudio = 1,
+ // tracking video codec
+ kBatteryDataTrackVideo = 2,
+ // codec is started, otherwise codec is paused
+ kBatteryDataCodecStarted = 4,
+ // tracking decoder (for media player),
+ // otherwise tracking encoder (for media recorder)
+ kBatteryDataTrackDecoder = 8,
+ };
+
+ virtual void addBatteryData(uint32_t params) = 0;
+ virtual status_t pullBatteryData(Parcel* reply) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index c24c0dbcb28f..f8d96cf1e84c 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -18,7 +18,6 @@
#define ANDROID_REF_BASE_H
#include <cutils/atomic.h>
-#include <utils/TextOutput.h>
#include <stdint.h>
#include <sys/types.h>
@@ -27,6 +26,10 @@
// ---------------------------------------------------------------------------
namespace android {
+class TextOutput;
+TextOutput& printStrongPointer(TextOutput& to, const void* val);
+TextOutput& printWeakPointer(TextOutput& to, const void* val);
+
template<typename T> class wp;
// ---------------------------------------------------------------------------
@@ -427,8 +430,7 @@ sp<T>::sp(T* p, weakref_type* refs)
template <typename T>
inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
{
- to << "sp<>(" << val.get() << ")";
- return to;
+ return printStrongPointer(to, val.get());
}
// ---------------------------------------------------------------------------
@@ -585,8 +587,7 @@ void wp<T>::clear()
template <typename T>
inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
{
- to << "wp<>(" << val.unsafe_get() << ")";
- return to;
+ return printWeakPointer(to, val.unsafe_get());
}
}; // namespace android
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index 907f119b8174..e2883121e497 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -301,12 +301,12 @@ status_t Camera::cancelAutoFocus()
}
// take a picture
-status_t Camera::takePicture()
+status_t Camera::takePicture(int msgType)
{
- LOGV("takePicture");
+ LOGV("takePicture: 0x%x", msgType);
sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT;
- return c->takePicture();
+ return c->takePicture(msgType);
}
// set preview/capture parameters - key/value pairs
diff --git a/libs/camera/ICamera.cpp b/libs/camera/ICamera.cpp
index 0881d65ae3d2..931b57d048aa 100644
--- a/libs/camera/ICamera.cpp
+++ b/libs/camera/ICamera.cpp
@@ -223,11 +223,12 @@ public:
}
// take a picture - returns an IMemory (ref-counted mmap)
- status_t takePicture()
+ status_t takePicture(int msgType)
{
- LOGV("takePicture");
+ LOGV("takePicture: 0x%x", msgType);
Parcel data, reply;
data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeInt32(msgType);
remote()->transact(TAKE_PICTURE, data, &reply);
status_t ret = reply.readInt32();
return ret;
@@ -401,7 +402,8 @@ status_t BnCamera::onTransact(
case TAKE_PICTURE: {
LOGV("TAKE_PICTURE");
CHECK_INTERFACE(ICamera, data, reply);
- reply->writeInt32(takePicture());
+ int msgType = data.readInt32();
+ reply->writeInt32(takePicture(msgType));
return NO_ERROR;
} break;
case SET_PARAMETERS: {
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index 0bd1af4ebf18..f934eec80f80 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -23,6 +23,7 @@
#include <utils/KeyedVector.h>
#include <utils/Log.h>
#include <utils/threads.h>
+#include <utils/TextOutput.h>
#include <stdlib.h>
#include <stdio.h>
@@ -530,5 +531,20 @@ bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
void RefBase::onLastWeakRef(const void* /*id*/)
{
}
-
+
+// ---------------------------------------------------------------------------
+
+TextOutput& printStrongPointer(TextOutput& to, const void* val)
+{
+ to << "sp<>(" << val << ")";
+ return to;
+}
+
+TextOutput& printWeakPointer(TextOutput& to, const void* val)
+{
+ to << "wp<>(" << val << ")";
+ return to;
+}
+
+
}; // namespace android
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 98ddbe70ac90..9c92ace2f47e 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1235,6 +1235,14 @@ public class MediaPlayer
private native final void native_setup(Object mediaplayer_this);
private native final void native_finalize();
+ /**
+ * @param reply Parcel with audio/video duration info for battery
+ tracking usage
+ * @return The status code.
+ * {@hide}
+ */
+ public native static int native_pullBatteryData(Parcel reply);
+
@Override
protected void finalize() { native_finalize(); }
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index ad2bf954543e..e0df257eca55 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3807,7 +3807,6 @@ class MediaArtistNativeHelper {
} catch (Throwable e) {
// Allocating to new size with Fixed count
try {
- System.gc();
rgb888 = new int[thumbnailSize * MAX_THUMBNAIL_PERMITTED];
bitmaps = new Bitmap[MAX_THUMBNAIL_PERMITTED];
thumbnailCount = MAX_THUMBNAIL_PERMITTED;
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index 69088edd32b7..4faa83a02fe3 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -197,7 +197,6 @@ public class MediaImageItem extends MediaItem {
fl.close();
}
imageBitmap.recycle();
- System.gc();
}
/*
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 0884e350d769..ca544328952c 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -36,6 +36,8 @@
#include "android_util_Binder.h"
#include <binder/Parcel.h>
#include <surfaceflinger/Surface.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
// ----------------------------------------------------------------------------
@@ -723,6 +725,21 @@ static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz
process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
}
+static jint
+android_media_MediaPlayer_pullBatteryData(JNIEnv *env, jobject thiz, jobject java_reply)
+{
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+ if (service.get() == NULL) {
+ jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService");
+ return UNKNOWN_ERROR;
+ }
+
+ Parcel *reply = parcelForJavaObject(env, java_reply);
+
+ return service->pullBatteryData(reply);
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -758,6 +775,7 @@ static JNINativeMethod gMethods[] = {
{"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
{"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
{"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect},
+ {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData},
};
static const char* const kClassPathName = "android/media/MediaPlayer";
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 77199e12e719..17a0362862e0 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -37,7 +37,9 @@ enum {
DECODE_FD,
CREATE_MEDIA_RECORDER,
CREATE_METADATA_RETRIEVER,
- GET_OMX
+ GET_OMX,
+ ADD_BATTERY_DATA,
+ PULL_BATTERY_DATA
};
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
@@ -156,6 +158,19 @@ public:
remote()->transact(GET_OMX, data, &reply);
return interface_cast<IOMX>(reply.readStrongBinder());
}
+
+ virtual void addBatteryData(uint32_t params) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ data.writeInt32(params);
+ remote()->transact(ADD_BATTERY_DATA, data, &reply);
+ }
+
+ virtual status_t pullBatteryData(Parcel* reply) {
+ Parcel data;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ return remote()->transact(PULL_BATTERY_DATA, data, reply);
+ }
};
IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
@@ -270,6 +285,17 @@ status_t BnMediaPlayerService::onTransact(
reply->writeStrongBinder(omx->asBinder());
return NO_ERROR;
} break;
+ case ADD_BATTERY_DATA: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ uint32_t params = data.readInt32();
+ addBatteryData(params);
+ return NO_ERROR;
+ } break;
+ case PULL_BATTERY_DATA: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ pullBatteryData(reply);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 60bdd6233b91..8c6f76b19996 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <dirent.h>
#include <unistd.h>
@@ -51,6 +52,8 @@
#include <media/Metadata.h>
#include <media/AudioTrack.h>
+#include <private/android_filesystem_config.h>
+
#include "MediaRecorderClient.h"
#include "MediaPlayerService.h"
#include "MetadataRetrieverClient.h"
@@ -1762,4 +1765,93 @@ int MediaPlayerService::AudioCache::getSessionId()
return 0;
}
+void MediaPlayerService::addBatteryData(uint32_t params)
+{
+ Mutex::Autolock lock(mLock);
+ int uid = IPCThreadState::self()->getCallingUid();
+ if (uid == AID_MEDIA) {
+ return;
+ }
+ int index = mBatteryData.indexOfKey(uid);
+ int32_t time = systemTime() / 1000000L;
+
+ if (index < 0) { // create a new entry for this UID
+ BatteryUsageInfo info;
+ info.audioTotalTime = 0;
+ info.videoTotalTime = 0;
+ info.audioLastTime = 0;
+ info.videoLastTime = 0;
+ info.refCount = 0;
+
+ mBatteryData.add(uid, info);
+ }
+
+ BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
+
+ if (params & kBatteryDataCodecStarted) {
+ if (params & kBatteryDataTrackAudio) {
+ info.audioLastTime -= time;
+ info.refCount ++;
+ }
+ if (params & kBatteryDataTrackVideo) {
+ info.videoLastTime -= time;
+ info.refCount ++;
+ }
+ } else {
+ if (info.refCount == 0) {
+ LOGW("Battery track warning: refCount is already 0");
+ return;
+ } else if (info.refCount < 0) {
+ LOGE("Battery track error: refCount < 0");
+ mBatteryData.removeItem(uid);
+ return;
+ }
+
+ if (params & kBatteryDataTrackAudio) {
+ info.audioLastTime += time;
+ info.refCount --;
+ }
+ if (params & kBatteryDataTrackVideo) {
+ info.videoLastTime += time;
+ info.refCount --;
+ }
+
+ // no stream is being played by this UID
+ if (info.refCount == 0) {
+ info.audioTotalTime += info.audioLastTime;
+ info.audioLastTime = 0;
+ info.videoTotalTime += info.videoLastTime;
+ info.videoLastTime = 0;
+ }
+ }
+}
+
+status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
+ Mutex::Autolock lock(mLock);
+ BatteryUsageInfo info;
+ int size = mBatteryData.size();
+
+ reply->writeInt32(size);
+ int i = 0;
+
+ while (i < size) {
+ info = mBatteryData.valueAt(i);
+
+ reply->writeInt32(mBatteryData.keyAt(i)); //UID
+ reply->writeInt32(info.audioTotalTime);
+ reply->writeInt32(info.videoTotalTime);
+
+ info.audioTotalTime = 0;
+ info.videoTotalTime = 0;
+
+ // remove the UID entry where no stream is being played
+ if (info.refCount <= 0) {
+ mBatteryData.removeItemsAt(i);
+ size --;
+ i --;
+ }
+ i++;
+ }
+ return NO_ERROR;
+}
} // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 62f8ed67bf96..9f41db034028 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -204,7 +204,31 @@ public:
void removeClient(wp<Client> client);
+ // For battery usage tracking purpose
+ struct BatteryUsageInfo {
+ // how many streams are being played by one UID
+ int refCount;
+ // a temp variable to store the duration(ms) of audio codecs
+ // when we start a audio codec, we minus the system time from audioLastTime
+ // when we pause it, we add the system time back to the audioLastTime
+ // so after the pause, audioLastTime = pause time - start time
+ // if multiple audio streams are played (or recorded), then audioLastTime
+ // = the total playing time of all the streams
+ int32_t audioLastTime;
+ // when all the audio streams are being paused, we assign audioLastTime to
+ // this variable, so this value could be provided to the battery app
+ // in the next pullBatteryData call
+ int32_t audioTotalTime;
+
+ int32_t videoLastTime;
+ int32_t videoTotalTime;
+ };
+ KeyedVector<int, BatteryUsageInfo> mBatteryData;
+ // Collect info of the codec usage from media player and media recorder
+ virtual void addBatteryData(uint32_t params);
+ // API for the Battery app to pull the data of codecs usage
+ virtual status_t pullBatteryData(Parcel* reply);
private:
class Client : public BnMediaPlayer {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 87fdbf248c37..e3dfabb02493 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -20,6 +20,10 @@
#include "StagefrightRecorder.h"
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <media/IMediaPlayerService.h>
#include <media/stagefright/AudioSource.h>
#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/CameraSource.h>
@@ -46,9 +50,23 @@
namespace android {
+// To collect the encoder usage for the battery app
+static void addBatteryData(uint32_t params) {
+ sp<IBinder> binder =
+ defaultServiceManager()->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+ CHECK(service.get() != NULL);
+
+ service->addBatteryData(params);
+}
+
+
StagefrightRecorder::StagefrightRecorder()
: mWriter(NULL), mWriterAux(NULL),
- mOutputFd(-1), mOutputFdAux(-1) {
+ mOutputFd(-1), mOutputFdAux(-1),
+ mAudioSource(AUDIO_SOURCE_LIST_END),
+ mVideoSource(VIDEO_SOURCE_LIST_END),
+ mStarted(false) {
LOGV("Constructor");
reset();
@@ -745,30 +763,54 @@ status_t StagefrightRecorder::start() {
return UNKNOWN_ERROR;
}
+ status_t status = OK;
+
switch (mOutputFormat) {
case OUTPUT_FORMAT_DEFAULT:
case OUTPUT_FORMAT_THREE_GPP:
case OUTPUT_FORMAT_MPEG_4:
- return startMPEG4Recording();
+ status = startMPEG4Recording();
+ break;
case OUTPUT_FORMAT_AMR_NB:
case OUTPUT_FORMAT_AMR_WB:
- return startAMRRecording();
+ status = startAMRRecording();
+ break;
case OUTPUT_FORMAT_AAC_ADIF:
case OUTPUT_FORMAT_AAC_ADTS:
- return startAACRecording();
+ status = startAACRecording();
+ break;
case OUTPUT_FORMAT_RTP_AVP:
- return startRTPRecording();
+ status = startRTPRecording();
+ break;
case OUTPUT_FORMAT_MPEG2TS:
- return startMPEG2TSRecording();
+ status = startMPEG2TSRecording();
+ break;
default:
LOGE("Unsupported output file format: %d", mOutputFormat);
- return UNKNOWN_ERROR;
+ status = UNKNOWN_ERROR;
+ break;
+ }
+
+ if ((status == OK) && (!mStarted)) {
+ mStarted = true;
+
+ uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
+ if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+
+ addBatteryData(params);
}
+
+ return status;
}
sp<MediaSource> StagefrightRecorder::createAudioSource() {
@@ -1458,6 +1500,21 @@ status_t StagefrightRecorder::pause() {
mWriterAux->pause();
}
+ if (mStarted) {
+ mStarted = false;
+
+ uint32_t params = 0;
+ if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+
+ addBatteryData(params);
+ }
+
+
return OK;
}
@@ -1494,6 +1551,21 @@ status_t StagefrightRecorder::stop() {
}
}
+ if (mStarted) {
+ mStarted = false;
+
+ uint32_t params = 0;
+ if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+
+ addBatteryData(params);
+ }
+
+
return err;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 72225dbdd78d..2c440c1a0dec 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -107,6 +107,8 @@ private:
bool mIsMetaDataStoredInVideoBuffers;
MediaProfiles *mEncoderProfiles;
+ bool mStarted;
+
status_t setupMPEG4Recording(
bool useSplitCameraSource,
int outputFd,
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b1d3630c67df..1b63ab2461c4 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -28,6 +28,8 @@
#include "include/MPEG2TSExtractor.h"
#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/AudioPlayer.h>
@@ -155,8 +157,17 @@ private:
const AwesomeNativeWindowRenderer &);
};
-////////////////////////////////////////////////////////////////////////////////
+// To collect the decoder usage
+void addBatteryData(uint32_t params) {
+ sp<IBinder> binder =
+ defaultServiceManager()->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+ CHECK(service.get() != NULL);
+
+ service->addBatteryData(params);
+}
+////////////////////////////////////////////////////////////////////////////////
AwesomePlayer::AwesomePlayer()
: mQueueStarted(false),
mTimeSource(NULL),
@@ -379,6 +390,17 @@ void AwesomePlayer::reset_l() {
mDrmManagerClient = NULL;
}
+ if (mFlags & PLAYING) {
+ uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
+ if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != NULL) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+ addBatteryData(params);
+ }
+
if (mFlags & PREPARING) {
mFlags |= PREPARE_CANCELLED;
if (mConnectingDataSource != NULL) {
@@ -779,6 +801,16 @@ status_t AwesomePlayer::play_l() {
seekTo_l(0);
}
+ uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
+ | IMediaPlayerService::kBatteryDataTrackDecoder;
+ if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != NULL) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+ addBatteryData(params);
+
return OK;
}
@@ -933,6 +965,16 @@ status_t AwesomePlayer::pause_l(bool at_eos) {
Playback::PAUSE, 0);
}
+ uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
+ if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != NULL) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+
+ addBatteryData(params);
+
return OK;
}
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index e6fe6186d45b..3689557bbf92 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -277,7 +277,7 @@ void CameraSourceTimeLapse::threadTimeLapseEntry() {
// this thread as read() will make a copy of this last frame and keep
// returning it in the quick stop mode.
Mutex::Autolock autoLock(mQuickStopLock);
- CHECK_EQ(OK, mCamera->takePicture());
+ CHECK_EQ(OK, mCamera->takePicture(CAMERA_MSG_RAW_IMAGE));
if (mQuickStop) {
LOGV("threadTimeLapseEntry: Exiting due to mQuickStop = true");
return;
diff --git a/media/libstagefright/include/AMRExtractor.h b/media/libstagefright/include/AMRExtractor.h
index 589d8370e283..4a1c827453e1 100644
--- a/media/libstagefright/include/AMRExtractor.h
+++ b/media/libstagefright/include/AMRExtractor.h
@@ -18,6 +18,7 @@
#define AMR_EXTRACTOR_H_
+#include <utils/Errors.h>
#include <media/stagefright/MediaExtractor.h>
namespace android {
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index 728980e5c281..ef71b8f21e0f 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -18,6 +18,7 @@
#define MP3_EXTRACTOR_H_
+#include <utils/Errors.h>
#include <media/stagefright/MediaExtractor.h>
namespace android {
diff --git a/media/libstagefright/include/OggExtractor.h b/media/libstagefright/include/OggExtractor.h
index a41f681e7af2..e97c8cdef486 100644
--- a/media/libstagefright/include/OggExtractor.h
+++ b/media/libstagefright/include/OggExtractor.h
@@ -18,6 +18,7 @@
#define OGG_EXTRACTOR_H_
+#include <utils/Errors.h>
#include <media/stagefright/MediaExtractor.h>
namespace android {
diff --git a/media/libstagefright/include/WAVExtractor.h b/media/libstagefright/include/WAVExtractor.h
index 9de197f67839..ce1f33ad9ff7 100644
--- a/media/libstagefright/include/WAVExtractor.h
+++ b/media/libstagefright/include/WAVExtractor.h
@@ -18,6 +18,7 @@
#define WAV_EXTRACTOR_H_
+#include <utils/Errors.h>
#include <media/stagefright/MediaExtractor.h>
namespace android {
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index 02187552723a..afff8242a49c 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -19,6 +19,7 @@
#define AVC_UTILS_H_
#include <media/stagefright/foundation/ABuffer.h>
+#include <utils/Errors.h>
namespace android {
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index d08199533188..153cfe67fe98 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -19,6 +19,7 @@
#define ES_QUEUE_H_
#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
#include <utils/List.h>
#include <utils/RefBase.h>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 3d8ca7a3da13..a09e16b3b412 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -727,17 +727,30 @@ status_t CameraService::Client::cancelAutoFocus() {
}
// take a picture - image is returned in callback
-status_t CameraService::Client::takePicture() {
- LOG1("takePicture (pid %d)", getCallingPid());
+status_t CameraService::Client::takePicture(int msgType) {
+ LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
Mutex::Autolock lock(mLock);
status_t result = checkPidAndHardware();
if (result != NO_ERROR) return result;
- enableMsgType(CAMERA_MSG_SHUTTER |
- CAMERA_MSG_POSTVIEW_FRAME |
- CAMERA_MSG_RAW_IMAGE |
- CAMERA_MSG_COMPRESSED_IMAGE);
+ if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
+ (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
+ LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
+ " cannot be both enabled");
+ return BAD_VALUE;
+ }
+
+ // We only accept picture related message types
+ // and ignore other types of messages for takePicture().
+ int picMsgType = msgType
+ & (CAMERA_MSG_SHUTTER |
+ CAMERA_MSG_POSTVIEW_FRAME |
+ CAMERA_MSG_RAW_IMAGE |
+ CAMERA_MSG_RAW_IMAGE_NOTIFY |
+ CAMERA_MSG_COMPRESSED_IMAGE);
+
+ enableMsgType(picMsgType);
return mHardware->takePicture();
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ccb9cf7082cc..1c43b00f7ff1 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -108,7 +108,7 @@ private:
virtual void releaseRecordingFrame(const sp<IMemory>& mem);
virtual status_t autoFocus();
virtual status_t cancelAutoFocus();
- virtual status_t takePicture();
+ virtual status_t takePicture(int msgType);
virtual status_t setParameters(const String8& params);
virtual String8 getParameters() const;
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index cc25e8d09996..f9b94a309f25 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -96,6 +96,9 @@ public class WifiService extends IWifiManager.Stub {
private boolean mDeviceIdle;
private int mPluggedType;
+ /* Chipset supports background scan */
+ private final boolean mBackgroundScanSupported;
+
// true if the user enabled Wifi while in airplane mode
private AtomicBoolean mAirplaneModeOverwridden = new AtomicBoolean(false);
@@ -369,6 +372,9 @@ public class WifiService extends IWifiManager.Stub {
Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(new Handler());
mNotificationEnabledSettingObserver.register();
+
+ mBackgroundScanSupported = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_wifi_background_scan_support);
}
/**
@@ -900,6 +906,9 @@ public class WifiService extends IWifiManager.Stub {
reportStartWorkSource();
evaluateTrafficStatsPolling();
mWifiStateMachine.enableRssiPolling(true);
+ if (mBackgroundScanSupported) {
+ mWifiStateMachine.enableBackgroundScan(false);
+ }
mWifiStateMachine.enableAllNetworks();
updateWifiState();
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
@@ -909,6 +918,9 @@ public class WifiService extends IWifiManager.Stub {
mScreenOff = true;
evaluateTrafficStatsPolling();
mWifiStateMachine.enableRssiPolling(false);
+ if (mBackgroundScanSupported) {
+ mWifiStateMachine.enableBackgroundScan(true);
+ }
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
* AND the "stay on while plugged in" setting doesn't match the
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0f7d6392e496..57af001fabc8 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -341,6 +341,45 @@ void Layer::onDraw(const Region& clip) const
drawWithOpenGL(clip, tex);
}
+// As documented in libhardware header, formats in the range
+// 0x100 - 0x1FF are specific to the HAL implementation, and
+// are known to have no alpha channel
+// TODO: move definition for device-specific range into
+// hardware.h, instead of using hard-coded values here.
+#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
+
+bool Layer::needsBlending(const sp<GraphicBuffer>& buffer) const
+{
+ // If buffers where set with eOpaque flag, all buffers are known to
+ // be opaque without having to check their actual format
+ if (mNeedsBlending && buffer != NULL) {
+ PixelFormat format = buffer->getPixelFormat();
+
+ if (HARDWARE_IS_DEVICE_FORMAT(format)) {
+ return false;
+ }
+
+ PixelFormatInfo info;
+ status_t err = getPixelFormatInfo(format, &info);
+ if (!err && info.h_alpha <= info.l_alpha) {
+ return false;
+ }
+ }
+
+ // Return opacity as determined from flags and format options
+ // passed to setBuffers()
+ return mNeedsBlending;
+}
+
+bool Layer::needsBlending() const
+{
+ if (mBufferManager.hasActiveBuffer()) {
+ return needsBlending(mBufferManager.getActiveBuffer());
+ }
+
+ return mNeedsBlending;
+}
+
bool Layer::needsFiltering() const
{
if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
@@ -588,6 +627,9 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// we retired a buffer, which becomes the new front buffer
const bool noActiveBuffer = !mBufferManager.hasActiveBuffer();
+ const bool activeBlending =
+ noActiveBuffer ? true : needsBlending(mBufferManager.getActiveBuffer());
+
if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
mPostedDirtyRegion.clear();
@@ -602,6 +644,12 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
if (newFrontBuffer != NULL) {
+ if (!noActiveBuffer && activeBlending != needsBlending(newFrontBuffer)) {
+ // new buffer has different opacity than previous active buffer, need
+ // to recompute visible regions accordingly
+ recomputeVisibleRegions = true;
+ }
+
// get the dirty region
// compute the posted region
const Region dirty(lcblk->getDirtyRegion(buf));
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2b3841466d70..bccc9004fd99 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -75,7 +75,8 @@ public:
virtual uint32_t doTransaction(uint32_t transactionFlags);
virtual void lockPageFlip(bool& recomputeVisibleRegions);
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
- virtual bool needsBlending() const { return mNeedsBlending; }
+ virtual bool needsBlending(const sp<GraphicBuffer>& buffer) const;
+ virtual bool needsBlending() const;
virtual bool needsDithering() const { return mNeedsDithering; }
virtual bool needsFiltering() const;
virtual bool isSecure() const { return mSecure; }
diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
index 5211b0a9b6e0..d3c492eacf43 100644
--- a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
+++ b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
@@ -9,5 +9,7 @@
android:layout_width="wrap_content"/>
<ImageView
android:layout_height="wrap_content"
- android:layout_width="wrap_content"/>
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="3dip"
+ android:layout_marginRight="5dip"/>
</merge>
diff --git a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
index e1934774f672..a50a2bd039f5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
@@ -63,7 +63,7 @@ public class AvoidXfermode_Delegate extends Xfermode_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreate(int opColor, int tolerance, int nativeMode) {
AvoidXfermode_Delegate newDelegate = new AvoidXfermode_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
index c6fde7be289b..9a8cf0462131 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
@@ -76,7 +76,7 @@ public class BitmapShader_Delegate extends Shader_Delegate {
bitmap.getImage(),
Shader_Delegate.getTileMode(shaderTileModeX),
Shader_Delegate.getTileMode(shaderTileModeY));
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 0c8776628646..b6d5725ab07b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -245,12 +245,12 @@ public final class Bitmap_Delegate {
@LayoutlibDelegate
/*package*/ static void nativeDestructor(int nativeBitmap) {
- sManager.removeDelegate(nativeBitmap);
+ sManager.removeJavaReferenceFor(nativeBitmap);
}
@LayoutlibDelegate
/*package*/ static void nativeRecycle(int nativeBitmap) {
- sManager.removeDelegate(nativeBitmap);
+ sManager.removeJavaReferenceFor(nativeBitmap);
}
@LayoutlibDelegate
@@ -522,7 +522,7 @@ public final class Bitmap_Delegate {
private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
// get its native_int
- int nativeInt = sManager.addDelegate(delegate);
+ int nativeInt = sManager.addNewDelegate(delegate);
// and create/return a new Bitmap with it
return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, density);
diff --git a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java
index 92d0d0af5d3f..4becba130127 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java
@@ -57,7 +57,7 @@ public class BlurMaskFilter_Delegate extends MaskFilter_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeConstructor(float radius, int style) {
BlurMaskFilter_Delegate newDelegate = new BlurMaskFilter_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index e8a99b5d6711..f0e727febe96 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -64,7 +64,7 @@ public final class Canvas_Delegate {
private Bitmap_Delegate mBitmap;
private GcSnapshot mSnapshot;
- private int mDrawFilter = 0;
+ private DrawFilter_Delegate mDrawFilter = null;
// ---- Public Helper methods ----
@@ -95,7 +95,7 @@ public final class Canvas_Delegate {
* @return the delegate or null.
*/
public DrawFilter_Delegate getDrawFilter() {
- return DrawFilter_Delegate.getDelegate(mDrawFilter);
+ return mDrawFilter;
}
// ---- native methods ----
@@ -313,12 +313,12 @@ public final class Canvas_Delegate {
// create a new Canvas_Delegate with the given bitmap and return its new native int.
Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate);
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
} else {
// create a new Canvas_Delegate and return its new native int.
Canvas_Delegate newDelegate = new Canvas_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
}
@@ -510,26 +510,18 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void nativeSetDrawFilter(int nativeCanvas,
- int nativeFilter) {
+ /*package*/ static void nativeSetDrawFilter(int nativeCanvas, int nativeFilter) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
- canvasDelegate.mDrawFilter = nativeFilter;
+ canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter);
- // get the delegate only because we don't support them at all for the moment, so
- // we can display the message now.
-
- DrawFilter_Delegate filterDelegate = DrawFilter_Delegate.getDelegate(nativeFilter);
- if (canvasDelegate == null) {
- return;
- }
-
- if (filterDelegate.isSupported() == false) {
+ if (canvasDelegate.mDrawFilter != null &&
+ canvasDelegate.mDrawFilter.isSupported() == false) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
- filterDelegate.getSupportMessage(), null, null /*data*/);
+ canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/);
}
}
@@ -956,7 +948,7 @@ public final class Canvas_Delegate {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
public void draw(Graphics2D graphics, Paint_Delegate paint) {
- // WARNING: the logic in this method is similar to Paint.measureText.
+ // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
// Any change to this method should be reflected in Paint.measureText
// Paint.TextAlign indicates how the text is positioned relative to X.
// LEFT is the default and there's nothing to do.
@@ -1139,7 +1131,7 @@ public final class Canvas_Delegate {
canvasDelegate.dispose();
// remove it from the manager.
- sManager.removeDelegate(nativeCanvas);
+ sManager.removeJavaReferenceFor(nativeCanvas);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
index 789c6e6904bf..e786eb587b1d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
@@ -57,7 +57,7 @@ public abstract class ColorFilter_Delegate {
@LayoutlibDelegate
/*package*/ static void finalizer(int native_instance, int nativeColorFilter) {
- sManager.removeDelegate(native_instance);
+ sManager.removeJavaReferenceFor(native_instance);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
index 462b1e640725..2de344b41f8a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
@@ -57,7 +57,7 @@ public class ColorMatrixColorFilter_Delegate extends ColorFilter_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeColorMatrixFilter(float[] array) {
ColorMatrixColorFilter_Delegate newDelegate = new ColorMatrixColorFilter_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java
index 2bdaa5bdbf5c..7c04a8709db2 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java
@@ -64,7 +64,7 @@ public class ComposePathEffect_Delegate extends PathEffect_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreate(int outerpe, int innerpe) {
ComposePathEffect_Delegate newDelegate = new ComposePathEffect_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
index a2ecb8f6a1a6..f6e1d0094925 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
@@ -67,7 +67,7 @@ public class ComposeShader_Delegate extends Shader_Delegate {
int native_mode) {
// FIXME not supported yet.
ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
@@ -75,7 +75,7 @@ public class ComposeShader_Delegate extends Shader_Delegate {
int porterDuffMode) {
// FIXME not supported yet.
ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java
index c677de83ba7f..b0f8168aa3a0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java
@@ -64,7 +64,7 @@ public class CornerPathEffect_Delegate extends PathEffect_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreate(float radius) {
CornerPathEffect_Delegate newDelegate = new CornerPathEffect_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
index 12a4d4a348d9..d97c2eccd508 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
@@ -75,7 +75,7 @@ public final class DashPathEffect_Delegate extends PathEffect_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreate(float intervals[], float phase) {
DashPathEffect_Delegate newDelegate = new DashPathEffect_Delegate(intervals, phase);
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java
index ac6971284583..ec4a810fbda5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java
@@ -64,7 +64,7 @@ public class DiscretePathEffect_Delegate extends PathEffect_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreate(float length, float deviation) {
DiscretePathEffect_Delegate newDelegate = new DiscretePathEffect_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java
index a98f0a941090..37c7359b5814 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java
@@ -57,7 +57,7 @@ public abstract class DrawFilter_Delegate {
@LayoutlibDelegate
/*package*/ static void nativeDestructor(int nativeDrawFilter) {
- sManager.removeDelegate(nativeDrawFilter);
+ sManager.removeJavaReferenceFor(nativeDrawFilter);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java
index 31f8bbfb1f8e..ebc1c1d2eca4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java
@@ -58,7 +58,7 @@ public class EmbossMaskFilter_Delegate extends MaskFilter_Delegate {
/*package*/ static int nativeConstructor(float[] direction, float ambient,
float specular, float blurRadius) {
EmbossMaskFilter_Delegate newDelegate = new EmbossMaskFilter_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
index fcb62a8a9592..51e0576169c4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
@@ -57,7 +57,7 @@ public class LayerRasterizer_Delegate extends Rasterizer_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeConstructor() {
LayerRasterizer_Delegate newDelegate = new LayerRasterizer_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
index b2725343b791..0ee883dcd68c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
@@ -57,7 +57,7 @@ public class LightingColorFilter_Delegate extends ColorFilter_Delegate {
@LayoutlibDelegate
/*package*/ static int native_CreateLightingFilter(int mul, int add) {
LightingColorFilter_Delegate newDelegate = new LightingColorFilter_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index 80605779fcf9..a2ba758a7e0c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -59,7 +59,7 @@ public final class LinearGradient_Delegate extends Gradient_Delegate {
int colors[], float positions[], int tileMode) {
LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(x0, y0, x1, y1,
colors, positions, Shader_Delegate.getTileMode(tileMode));
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java
index 4adca276a7d8..5a6167dc6a3d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java
@@ -57,7 +57,7 @@ public abstract class MaskFilter_Delegate {
@LayoutlibDelegate
/*package*/ static void nativeDestructor(int native_filter) {
- sManager.removeDelegate(native_filter);
+ sManager.removeJavaReferenceFor(native_filter);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 68a476f170ef..251aa16ba48b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -189,7 +189,7 @@ public final class Matrix_Delegate {
}
}
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
@@ -765,7 +765,7 @@ public final class Matrix_Delegate {
@LayoutlibDelegate
/*package*/ static void finalizer(int native_instance) {
- sManager.removeDelegate(native_instance);
+ sManager.removeJavaReferenceFor(native_instance);
}
// ---- Private helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java
index dfcb5916b8cc..71d346a93553 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java
@@ -57,7 +57,7 @@ public class PaintFlagsDrawFilter_Delegate extends DrawFilter_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeConstructor(int clearBits, int setBits) {
PaintFlagsDrawFilter_Delegate newDelegate = new PaintFlagsDrawFilter_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index f5d2547799d8..51b3efe12cd7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -32,6 +32,7 @@ import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -75,19 +76,19 @@ public class Paint_Delegate {
private int mCap;
private int mJoin;
private int mTextAlign;
- private int mTypeface;
+ private Typeface_Delegate mTypeface;
private float mStrokeWidth;
private float mStrokeMiter;
private float mTextSize;
private float mTextScaleX;
private float mTextSkewX;
- private int mXfermode;
- private int mColorFilter;
- private int mShader;
- private int mPathEffect;
- private int mMaskFilter;
- private int mRasterizer;
+ private Xfermode_Delegate mXfermode;
+ private ColorFilter_Delegate mColorFilter;
+ private Shader_Delegate mShader;
+ private PathEffect_Delegate mPathEffect;
+ private MaskFilter_Delegate mMaskFilter;
+ private Rasterizer_Delegate mRasterizer;
// ---- Public Helper methods ----
@@ -172,17 +173,16 @@ public class Paint_Delegate {
}
public Stroke getJavaStroke() {
- PathEffect_Delegate effectDelegate = PathEffect_Delegate.getDelegate(mPathEffect);
- if (effectDelegate != null) {
- if (effectDelegate.isSupported()) {
- Stroke stroke = effectDelegate.getStroke(this);
+ if (mPathEffect != null) {
+ if (mPathEffect.isSupported()) {
+ Stroke stroke = mPathEffect.getStroke(this);
assert stroke != null;
if (stroke != null) {
return stroke;
}
} else {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
- effectDelegate.getSupportMessage(),
+ mPathEffect.getSupportMessage(),
null, null /*data*/);
}
}
@@ -201,7 +201,7 @@ public class Paint_Delegate {
* @return the delegate or null.
*/
public Xfermode_Delegate getXfermode() {
- return Xfermode_Delegate.getDelegate(mXfermode);
+ return mXfermode;
}
/**
@@ -210,7 +210,7 @@ public class Paint_Delegate {
* @return the delegate or null.
*/
public ColorFilter_Delegate getColorFilter() {
- return ColorFilter_Delegate.getDelegate(mColorFilter);
+ return mColorFilter;
}
/**
@@ -219,7 +219,7 @@ public class Paint_Delegate {
* @return the delegate or null.
*/
public Shader_Delegate getShader() {
- return Shader_Delegate.getDelegate(mShader);
+ return mShader;
}
/**
@@ -228,7 +228,7 @@ public class Paint_Delegate {
* @return the delegate or null.
*/
public MaskFilter_Delegate getMaskFilter() {
- return MaskFilter_Delegate.getDelegate(mMaskFilter);
+ return mMaskFilter;
}
/**
@@ -237,7 +237,7 @@ public class Paint_Delegate {
* @return the delegate or null.
*/
public Rasterizer_Delegate getRasterizer() {
- return Rasterizer_Delegate.getDelegate(mRasterizer);
+ return mRasterizer;
}
// ---- native methods ----
@@ -542,9 +542,6 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
int count) {
- // WARNING: the logic in this method is similar to Canvas.drawText.
- // Any change to this method should be reflected in Canvas.drawText
-
// get the delegate
Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
if (delegate == null) {
@@ -567,25 +564,57 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count,
float maxWidth, float[] measuredWidth) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.native_breakText is not supported.", null, null /*data*/);
- return 0;
+
+ // get the delegate
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ if (delegate == null) {
+ return 0;
+ }
+
+ int inc = count > 0 ? 1 : -1;
+
+ int measureIndex = 0;
+ float measureAcc = 0;
+ for (int i = index; i != index + count; i += inc, measureIndex++) {
+ int start, end;
+ if (i < index) {
+ start = i;
+ end = index;
+ } else {
+ start = index;
+ end = i;
+ }
+
+ // measure from start to end
+ float res = delegate.measureText(text, start, end - start + 1);
+
+ if (measuredWidth != null) {
+ measuredWidth[measureIndex] = res;
+ }
+
+ measureAcc += res;
+ if (res > maxWidth) {
+ // we should not return this char index, but since it's 0-based
+ // and we need to return a count, we simply return measureIndex;
+ return measureIndex;
+ }
+
+ }
+
+ return measureIndex;
}
@LayoutlibDelegate
/*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards,
float maxWidth, float[] measuredWidth) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.native_breakText is not supported.", null, null /*data*/);
- return 0;
+ return native_breakText(thisPaint, text.toCharArray(), 0, text.length(), maxWidth,
+ measuredWidth);
}
@LayoutlibDelegate
/*package*/ static int native_init() {
Paint_Delegate newDelegate = new Paint_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
@@ -597,7 +626,7 @@ public class Paint_Delegate {
}
Paint_Delegate newDelegate = new Paint_Delegate(delegate);
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
@@ -728,7 +757,9 @@ public class Paint_Delegate {
return shader;
}
- return delegate.mShader = shader;
+ delegate.mShader = Shader_Delegate.getDelegate(shader);
+
+ return shader;
}
@LayoutlibDelegate
@@ -739,13 +770,12 @@ public class Paint_Delegate {
return filter;
}
- delegate.mColorFilter = filter;
+ delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);;
// since none of those are supported, display a fidelity warning right away
- ColorFilter_Delegate filterDelegate = delegate.getColorFilter();
- if (filterDelegate != null && filterDelegate.isSupported() == false) {
+ if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
- filterDelegate.getSupportMessage(), null, null /*data*/);
+ delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
}
return filter;
@@ -759,7 +789,9 @@ public class Paint_Delegate {
return xfermode;
}
- return delegate.mXfermode = xfermode;
+ delegate.mXfermode = Xfermode_Delegate.getDelegate(xfermode);
+
+ return xfermode;
}
@LayoutlibDelegate
@@ -770,7 +802,9 @@ public class Paint_Delegate {
return effect;
}
- return delegate.mPathEffect = effect;
+ delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect);
+
+ return effect;
}
@LayoutlibDelegate
@@ -781,13 +815,12 @@ public class Paint_Delegate {
return maskfilter;
}
- delegate.mMaskFilter = maskfilter;
+ delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
// since none of those are supported, display a fidelity warning right away
- MaskFilter_Delegate filterDelegate = delegate.getMaskFilter();
- if (filterDelegate != null && filterDelegate.isSupported() == false) {
+ if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
- filterDelegate.getSupportMessage(), null, null /*data*/);
+ delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
}
return maskfilter;
@@ -801,9 +834,9 @@ public class Paint_Delegate {
return 0;
}
- delegate.mTypeface = typeface;
+ delegate.mTypeface = Typeface_Delegate.getDelegate(typeface);
delegate.updateFontObject();
- return delegate.mTypeface;
+ return typeface;
}
@LayoutlibDelegate
@@ -814,13 +847,12 @@ public class Paint_Delegate {
return rasterizer;
}
- delegate.mRasterizer = rasterizer;
+ delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer);
// since none of those are supported, display a fidelity warning right away
- Rasterizer_Delegate rasterizerDelegate = delegate.getRasterizer();
- if (rasterizerDelegate != null && rasterizerDelegate.isSupported() == false) {
+ if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
- rasterizerDelegate.getSupportMessage(), null, null /*data*/);
+ delegate.mRasterizer.getSupportMessage(), null, null /*data*/);
}
return rasterizer;
@@ -862,19 +894,49 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static int native_getTextWidths(int native_object, char[] text, int index,
int count, float[] widths) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.getTextWidths is not supported.", null, null /*data*/);
+ // get the delegate from the native int.
+ Paint_Delegate delegate = sManager.getDelegate(native_object);
+ if (delegate == null) {
+ return 0;
+ }
+
+ if (delegate.mFonts.size() > 0) {
+ // FIXME: handle multi-char characters (see measureText)
+ float totalAdvance = 0;
+ for (int i = 0; i < count; i++) {
+ char c = text[i + index];
+ boolean found = false;
+ for (FontInfo info : delegate.mFonts) {
+ if (info.mFont.canDisplay(c)) {
+ float adv = info.mMetrics.charWidth(c);
+ totalAdvance += adv;
+ if (widths != null) {
+ widths[i] = adv;
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (found == false) {
+ // no advance for this char.
+ if (widths != null) {
+ widths[i] = 0.f;
+ }
+ }
+ }
+
+ return (int) totalAdvance;
+ }
+
return 0;
}
@LayoutlibDelegate
/*package*/ static int native_getTextWidths(int native_object, String text, int start,
int end, float[] widths) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.getTextWidths is not supported.", null, null /*data*/);
- return 0;
+ return native_getTextWidths(native_object, text.toCharArray(), start, end - start, widths);
}
@LayoutlibDelegate
@@ -971,22 +1033,33 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void nativeGetStringBounds(int nativePaint, String text, int start,
int end, Rect bounds) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.getStringBounds is not supported.", null, null /*data*/);
+ nativeGetCharArrayBounds(nativePaint, text.toCharArray(), start, end - start, bounds);
}
@LayoutlibDelegate
/*package*/ static void nativeGetCharArrayBounds(int nativePaint, char[] text, int index,
int count, Rect bounds) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.getCharArrayBounds is not supported.", null, null /*data*/);
+
+ // get the delegate from the native int.
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
+ if (delegate == null) {
+ return;
+ }
+
+ // FIXME should test if the main font can display all those characters.
+ // See MeasureText
+ if (delegate.mFonts.size() > 0) {
+ FontInfo mainInfo = delegate.mFonts.get(0);
+
+ Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count,
+ delegate.mFontContext);
+ bounds.set(0, 0, (int) rect.getWidth(), (int) rect.getHeight());
+ }
}
@LayoutlibDelegate
/*package*/ static void finalizer(int nativePaint) {
- sManager.removeDelegate(nativePaint);
+ sManager.removeJavaReferenceFor(nativePaint);
}
// ---- Private delegate/helper methods ----
@@ -1028,18 +1101,18 @@ public class Paint_Delegate {
mCap = Paint.Cap.BUTT.nativeInt;
mJoin = Paint.Join.MITER.nativeInt;
mTextAlign = 0;
- mTypeface = Typeface.sDefaults[0].native_instance;
+ mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance);
mStrokeWidth = 1.f;
mStrokeMiter = 4.f;
mTextSize = 20.f;
mTextScaleX = 1.f;
mTextSkewX = 0.f;
- mXfermode = 0;
- mColorFilter = 0;
- mShader = 0;
- mPathEffect = 0;
- mMaskFilter = 0;
- mRasterizer = 0;
+ mXfermode = null;
+ mColorFilter = null;
+ mShader = null;
+ mPathEffect = null;
+ mMaskFilter = null;
+ mRasterizer = null;
updateFontObject();
}
@@ -1048,9 +1121,9 @@ public class Paint_Delegate {
*/
@SuppressWarnings("deprecation")
private void updateFontObject() {
- if (mTypeface != 0) {
+ if (mTypeface != null) {
// Get the fonts from the TypeFace object.
- List<Font> fonts = Typeface_Delegate.getFonts(mTypeface);
+ List<Font> fonts = mTypeface.getFonts();
// create new font objects as well as FontMetrics, based on the current text size
// and skew info.
@@ -1073,6 +1146,10 @@ public class Paint_Delegate {
}
/*package*/ float measureText(char[] text, int index, int count) {
+
+ // WARNING: the logic in this method is similar to Canvas_Delegate.native_drawText
+ // Any change to this method should be reflected there as well
+
if (mFonts.size() > 0) {
FontInfo mainFont = mFonts.get(0);
int i = index;
@@ -1120,6 +1197,8 @@ public class Paint_Delegate {
i += size;
}
}
+
+ return total;
}
return 0;
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java
index 98a5386067a7..c448f0ec0f20 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java
@@ -65,7 +65,7 @@ public class PathDashPathEffect_Delegate extends PathEffect_Delegate {
/*package*/ static int nativeCreate(int native_path, float advance, float phase,
int native_style) {
PathDashPathEffect_Delegate newDelegate = new PathDashPathEffect_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
index bbbebdd8df2f..4d5311af42ae 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
@@ -61,7 +61,7 @@ public abstract class PathEffect_Delegate {
@LayoutlibDelegate
/*package*/ static void nativeDestructor(int native_patheffect) {
- sManager.removeDelegate(native_patheffect);
+ sManager.removeJavaReferenceFor(native_patheffect);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 9510ce00e214..c29e9b6a0142 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -90,7 +90,7 @@ public final class Path_Delegate {
// create the delegate
Path_Delegate newDelegate = new Path_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
@@ -104,7 +104,7 @@ public final class Path_Delegate {
newDelegate.set(pathDelegate);
}
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
@@ -440,7 +440,7 @@ public final class Path_Delegate {
@LayoutlibDelegate
/*package*/ static void finalizer(int nPath) {
- sManager.removeDelegate(nPath);
+ sManager.removeJavaReferenceFor(nPath);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
index bbb20e956163..4ab044bd107a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
@@ -63,7 +63,7 @@ public class PixelXorXfermode_Delegate extends Xfermode_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreate(int opColor) {
PixelXorXfermode_Delegate newDelegate = new PixelXorXfermode_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
index 33f6c4465527..c45dbaad344d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
@@ -57,7 +57,7 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
@LayoutlibDelegate
/*package*/ static int native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) {
PorterDuffColorFilter_Delegate newDelegate = new PorterDuffColorFilter_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
index 116a773c9832..4301c1a2c5d7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
@@ -129,7 +129,7 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreateXfermode(int mode) {
PorterDuffXfermode_Delegate newDelegate = new PorterDuffXfermode_Delegate(mode);
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index 8723ed1a6584..9bf78b4c7249 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -58,7 +58,7 @@ public class RadialGradient_Delegate extends Gradient_Delegate {
int colors[], float positions[], int tileMode) {
RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(x, y, radius,
colors, positions, Shader_Delegate.getTileMode(tileMode));
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
index 28262787f9ba..e388bd9fc1b0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
@@ -57,7 +57,7 @@ public abstract class Rasterizer_Delegate {
@LayoutlibDelegate
/*package*/ static void finalizer(int native_instance) {
- sManager.removeDelegate(native_instance);
+ sManager.removeJavaReferenceFor(native_instance);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index 7b912154930f..91f4347482ab 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -266,12 +266,12 @@ public class Region_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeConstructor() {
Region_Delegate newDelegate = new Region_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static void nativeDestructor(int native_region) {
- sManager.removeDelegate(native_region);
+ sManager.removeJavaReferenceFor(native_region);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index a1b8bdd12fdf..a008d151c6ae 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -45,7 +45,7 @@ public abstract class Shader_Delegate {
// ---- delegate helper data ----
// ---- delegate data ----
- private int mLocalMatrix = 0;
+ private Matrix_Delegate mLocalMatrix = null;
// ---- Public Helper methods ----
@@ -77,7 +77,7 @@ public abstract class Shader_Delegate {
@LayoutlibDelegate
/*package*/ static void nativeDestructor(int native_shader, int native_skiaShader) {
- sManager.removeDelegate(native_shader);
+ sManager.removeJavaReferenceFor(native_shader);
}
@LayoutlibDelegate
@@ -89,15 +89,14 @@ public abstract class Shader_Delegate {
return;
}
- shaderDelegate.mLocalMatrix = matrix_instance;
+ shaderDelegate.mLocalMatrix = Matrix_Delegate.getDelegate(matrix_instance);
}
// ---- Private delegate/helper methods ----
protected java.awt.geom.AffineTransform getLocalMatrix() {
- Matrix_Delegate localMatrixDelegate = Matrix_Delegate.getDelegate(mLocalMatrix);
- if (localMatrixDelegate != null) {
- return localMatrixDelegate.getAffineTransform();
+ if (mLocalMatrix != null) {
+ return mLocalMatrix.getAffineTransform();
}
return new java.awt.geom.AffineTransform();
diff --git a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java
index 0c9ee48ebd64..410df0cf72f5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java
@@ -64,7 +64,7 @@ public class SumPathEffect_Delegate extends PathEffect_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreate(int first, int second) {
SumPathEffect_Delegate newDelegate = new SumPathEffect_Delegate();
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index 382e34c41ad4..966e06e4a8b2 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -54,7 +54,7 @@ public class SweepGradient_Delegate extends Gradient_Delegate {
@LayoutlibDelegate
/*package*/ static int nativeCreate1(float x, float y, int colors[], float positions[]) {
SweepGradient_Delegate newDelegate = new SweepGradient_Delegate(x, y, colors, positions);
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 1992341d1423..5af16aeb5fb3 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -74,6 +74,10 @@ public final class Typeface_Delegate {
sPostInitDelegate.clear();
}
+ public static Typeface_Delegate getDelegate(int nativeTypeface) {
+ return sManager.getDelegate(nativeTypeface);
+ }
+
public static List<Font> getFonts(Typeface typeface) {
return getFonts(typeface.native_instance);
}
@@ -84,7 +88,11 @@ public final class Typeface_Delegate {
return null;
}
- return delegate.mFonts;
+ return delegate.getFonts();
+ }
+
+ public List<Font> getFonts() {
+ return mFonts;
}
// ---- native methods ----
@@ -105,7 +113,7 @@ public final class Typeface_Delegate {
sPostInitDelegate.add(newDelegate);
}
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
@@ -125,7 +133,7 @@ public final class Typeface_Delegate {
sPostInitDelegate.add(newDelegate);
}
- return sManager.addDelegate(newDelegate);
+ return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
@@ -144,7 +152,7 @@ public final class Typeface_Delegate {
@LayoutlibDelegate
/*package*/ static void nativeUnref(int native_instance) {
- sManager.removeDelegate(native_instance);
+ sManager.removeJavaReferenceFor(native_instance);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
index 88df02739c6e..f3401fcadb65 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
@@ -61,7 +61,7 @@ public abstract class Xfermode_Delegate {
@LayoutlibDelegate
/*package*/ static void finalizer(int native_instance) {
- sManager.removeDelegate(native_instance);
+ sManager.removeJavaReferenceFor(native_instance);
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
index 04d06e4bb45e..9fab51a61092 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
@@ -30,7 +30,7 @@ import android.widget.TextView;
public class PhoneSystemBar extends CustomBar {
public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
- super(context, density, "/bars/tablet_system_bar.xml");
+ super(context, density, "/bars/phone_system_bar.xml");
setGravity(mGravity | Gravity.RIGHT);
setBackgroundColor(0xFF000000);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index 05a258d56c66..295c98c3eafa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -16,8 +16,14 @@
package com.android.layoutlib.bridge.impl;
+import com.android.layoutlib.bridge.util.SparseWeakArray;
+
import android.util.SparseArray;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Manages native delegates.
*
@@ -44,13 +50,32 @@ import android.util.SparseArray;
* will do is call {@link #getDelegate(int)} to get the Java object matching the int.
*
* Typical native init methods are returning a new int back to the Java class, so
- * {@link #addDelegate(Object)} does the same.
+ * {@link #addNewDelegate(Object)} does the same.
+ *
+ * The JNI references are counted, so we do the same through a {@link WeakReference}. Because
+ * the Java object needs to count as a reference (even though it only holds an int), we use the
+ * following mechanism:
+ *
+ * - {@link #addNewDelegate(Object)} and {@link #removeJavaReferenceFor(int)} adds and removes
+ * the delegate to/from a list. This list hold the reference and prevents the GC from reclaiming
+ * the delegate.
+ *
+ * - {@link #addNewDelegate(Object)} also adds the delegate to a {@link SparseArray} that holds a
+ * {@link WeakReference} to the delegate. This allows the delegate to be deleted automatically
+ * when nothing references it. This means that any class that holds a delegate (except for the
+ * Java main class) must not use the int but the Delegate class instead. The integers must
+ * only be used in the API between the main Java class and the Delegate.
*
* @param <T> the delegate class to manage
*/
public final class DelegateManager<T> {
-
- private final SparseArray<T> mDelegates = new SparseArray<T>();
+ private final SparseWeakArray<T> mDelegates = new SparseWeakArray<T>();
+ /** list used to store delegates when their main object holds a reference to them.
+ * This is to ensure that the WeakReference in the SparseWeakArray doesn't get GC'ed
+ * @see #addNewDelegate(Object)
+ * @see #removeJavaReferenceFor(int)
+ */
+ private final List<T> mJavaReferences = new ArrayList<T>();
private int mDelegateCounter = 0;
/**
@@ -77,17 +102,20 @@ public final class DelegateManager<T> {
* @param newDelegate the delegate to add
* @return a unique native int to identify the delegate
*/
- public int addDelegate(T newDelegate) {
+ public int addNewDelegate(T newDelegate) {
int native_object = ++mDelegateCounter;
mDelegates.put(native_object, newDelegate);
+ assert !mJavaReferences.contains(newDelegate);
+ mJavaReferences.add(newDelegate);
return native_object;
}
/**
- * Removes the delegate matching the given native int.
- * @param native_object the native int.
+ * Removes the main reference on the given delegate.
+ * @param native_object the native integer representing the delegate.
*/
- public void removeDelegate(int native_object) {
- mDelegates.remove(native_object);
+ public void removeJavaReferenceFor(int native_object) {
+ T delegate = getDelegate(native_object);
+ mJavaReferences.remove(delegate);
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
new file mode 100644
index 000000000000..22f1609e6dc6
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.util;
+
+
+import com.android.internal.util.ArrayUtils;
+
+import android.util.SparseArray;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * This is a custom {@link SparseArray} that uses {@link WeakReference} around the objects added
+ * to it. When the array is compacted, not only deleted indices but also empty references
+ * are removed, making the array efficient at removing references that were reclaimed.
+ *
+ * The code is taken from {@link SparseArray} directly and adapted to use weak references.
+ *
+ * Because our usage means that we never actually call {@link #remove(int)} or {@link #delete(int)},
+ * we must manually check if there are reclaimed references to trigger an internal compact step
+ * (which is normally only triggered when an item is manually removed).
+ *
+ * SparseArrays map integers to Objects. Unlike a normal array of Objects,
+ * there can be gaps in the indices. It is intended to be more efficient
+ * than using a HashMap to map Integers to Objects.
+ */
+@SuppressWarnings("unchecked")
+public class SparseWeakArray<E> {
+
+ private static final Object DELETED_REF = new Object();
+ private static final WeakReference<?> DELETED = new WeakReference(DELETED_REF);
+ private boolean mGarbage = false;
+
+ /**
+ * Creates a new SparseArray containing no mappings.
+ */
+ public SparseWeakArray() {
+ this(10);
+ }
+
+ /**
+ * Creates a new SparseArray containing no mappings that will not
+ * require any additional memory allocation to store the specified
+ * number of mappings.
+ */
+ public SparseWeakArray(int initialCapacity) {
+ initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
+
+ mKeys = new int[initialCapacity];
+ mValues = new WeakReference[initialCapacity];
+ mSize = 0;
+ }
+
+ /**
+ * Gets the Object mapped from the specified key, or <code>null</code>
+ * if no such mapping has been made.
+ */
+ public E get(int key) {
+ return get(key, null);
+ }
+
+ /**
+ * Gets the Object mapped from the specified key, or the specified Object
+ * if no such mapping has been made.
+ */
+ public E get(int key, E valueIfKeyNotFound) {
+ int i = binarySearch(mKeys, 0, mSize, key);
+
+ if (i < 0 || mValues[i] == DELETED || mValues[i].get() == null) {
+ return valueIfKeyNotFound;
+ } else {
+ return (E) mValues[i].get();
+ }
+ }
+
+ /**
+ * Removes the mapping from the specified key, if there was any.
+ */
+ public void delete(int key) {
+ int i = binarySearch(mKeys, 0, mSize, key);
+
+ if (i >= 0) {
+ if (mValues[i] != DELETED) {
+ mValues[i] = DELETED;
+ mGarbage = true;
+ }
+ }
+ }
+
+ /**
+ * Alias for {@link #delete(int)}.
+ */
+ public void remove(int key) {
+ delete(key);
+ }
+
+ /**
+ * Removes the mapping at the specified index.
+ */
+ public void removeAt(int index) {
+ if (mValues[index] != DELETED) {
+ mValues[index] = DELETED;
+ mGarbage = true;
+ }
+ }
+
+ private void gc() {
+ // Log.e("SparseArray", "gc start with " + mSize);
+
+ int n = mSize;
+ int o = 0;
+ int[] keys = mKeys;
+ WeakReference<?>[] values = mValues;
+
+ for (int i = 0; i < n; i++) {
+ WeakReference<?> val = values[i];
+
+ // Don't keep any non DELETED values, but only the one that still have a valid
+ // reference.
+ if (val != DELETED && val.get() != null) {
+ if (i != o) {
+ keys[o] = keys[i];
+ values[o] = val;
+ }
+
+ o++;
+ }
+ }
+
+ mGarbage = false;
+ mSize = o;
+
+ // Log.e("SparseArray", "gc end with " + mSize);
+ }
+
+ /**
+ * Adds a mapping from the specified key to the specified value,
+ * replacing the previous mapping from the specified key if there
+ * was one.
+ */
+ public void put(int key, E value) {
+ int i = binarySearch(mKeys, 0, mSize, key);
+
+ if (i >= 0) {
+ mValues[i] = new WeakReference(value);
+ } else {
+ i = ~i;
+
+ if (i < mSize && (mValues[i] == DELETED || mValues[i].get() == null)) {
+ mKeys[i] = key;
+ mValues[i] = new WeakReference(value);
+ return;
+ }
+
+ if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) {
+ gc();
+
+ // Search again because indices may have changed.
+ i = ~binarySearch(mKeys, 0, mSize, key);
+ }
+
+ if (mSize >= mKeys.length) {
+ int n = ArrayUtils.idealIntArraySize(mSize + 1);
+
+ int[] nkeys = new int[n];
+ WeakReference<?>[] nvalues = new WeakReference[n];
+
+ // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
+ System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
+ System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
+
+ mKeys = nkeys;
+ mValues = nvalues;
+ }
+
+ if (mSize - i != 0) {
+ // Log.e("SparseArray", "move " + (mSize - i));
+ System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
+ System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
+ }
+
+ mKeys[i] = key;
+ mValues[i] = new WeakReference(value);
+ mSize++;
+ }
+ }
+
+ /**
+ * Returns the number of key-value mappings that this SparseArray
+ * currently stores.
+ */
+ public int size() {
+ if (mGarbage) {
+ gc();
+ }
+
+ return mSize;
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, returns
+ * the key from the <code>index</code>th key-value mapping that this
+ * SparseArray stores.
+ */
+ public int keyAt(int index) {
+ if (mGarbage) {
+ gc();
+ }
+
+ return mKeys[index];
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, returns
+ * the value from the <code>index</code>th key-value mapping that this
+ * SparseArray stores.
+ */
+ public E valueAt(int index) {
+ if (mGarbage) {
+ gc();
+ }
+
+ return (E) mValues[index].get();
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, sets a new
+ * value for the <code>index</code>th key-value mapping that this
+ * SparseArray stores.
+ */
+ public void setValueAt(int index, E value) {
+ if (mGarbage) {
+ gc();
+ }
+
+ mValues[index] = new WeakReference(value);
+ }
+
+ /**
+ * Returns the index for which {@link #keyAt} would return the
+ * specified key, or a negative number if the specified
+ * key is not mapped.
+ */
+ public int indexOfKey(int key) {
+ if (mGarbage) {
+ gc();
+ }
+
+ return binarySearch(mKeys, 0, mSize, key);
+ }
+
+ /**
+ * Returns an index for which {@link #valueAt} would return the
+ * specified key, or a negative number if no keys map to the
+ * specified value.
+ * Beware that this is a linear search, unlike lookups by key,
+ * and that multiple keys can map to the same value and this will
+ * find only one of them.
+ */
+ public int indexOfValue(E value) {
+ if (mGarbage) {
+ gc();
+ }
+
+ for (int i = 0; i < mSize; i++)
+ if (mValues[i].get() == value)
+ return i;
+
+ return -1;
+ }
+
+ /**
+ * Removes all key-value mappings from this SparseArray.
+ */
+ public void clear() {
+ int n = mSize;
+ WeakReference<?>[] values = mValues;
+
+ for (int i = 0; i < n; i++) {
+ values[i] = null;
+ }
+
+ mSize = 0;
+ mGarbage = false;
+ }
+
+ /**
+ * Puts a key/value pair into the array, optimizing for the case where
+ * the key is greater than all existing keys in the array.
+ */
+ public void append(int key, E value) {
+ if (mSize != 0 && key <= mKeys[mSize - 1]) {
+ put(key, value);
+ return;
+ }
+
+ if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) {
+ gc();
+ }
+
+ int pos = mSize;
+ if (pos >= mKeys.length) {
+ int n = ArrayUtils.idealIntArraySize(pos + 1);
+
+ int[] nkeys = new int[n];
+ WeakReference<?>[] nvalues = new WeakReference[n];
+
+ // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
+ System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
+ System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
+
+ mKeys = nkeys;
+ mValues = nvalues;
+ }
+
+ mKeys[pos] = key;
+ mValues[pos] = new WeakReference(value);
+ mSize = pos + 1;
+ }
+
+ private boolean hasReclaimedRefs() {
+ for (int i = 0 ; i < mSize ; i++) {
+ if (mValues[i].get() == null) { // DELETED.get() never returns null.
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static int binarySearch(int[] a, int start, int len, int key) {
+ int high = start + len, low = start - 1, guess;
+
+ while (high - low > 1) {
+ guess = (high + low) / 2;
+
+ if (a[guess] < key)
+ low = guess;
+ else
+ high = guess;
+ }
+
+ if (high == start + len)
+ return ~(start + len);
+ else if (a[high] == key)
+ return high;
+ else
+ return ~high;
+ }
+
+ private int[] mKeys;
+ private WeakReference<?>[] mValues;
+ private int mSize;
+}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 39676b044001..909605dc55d4 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -170,4 +170,6 @@ public class WifiNative {
* @return the event string sent by the supplicant.
*/
public native static String waitForEvent();
+
+ public native static void enableBackgroundScan(boolean enable);
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index fc42ab8bdad9..676218e9eb4c 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -112,9 +112,11 @@ public class WifiStateMachine extends HierarchicalStateMachine {
private String mLastBssid;
private int mLastNetworkId;
private boolean mEnableRssiPolling = false;
+ private boolean mEnableBackgroundScan = false;
private int mRssiPollToken = 0;
private int mReconnectCount = 0;
private boolean mIsScanMode = false;
+ private boolean mScanResultIsPending = false;
private boolean mBluetoothConnectionActive = false;
@@ -300,6 +302,8 @@ public class WifiStateMachine extends HierarchicalStateMachine {
static final int CMD_START_WPS = 89;
/* Set the frequency band */
static final int CMD_SET_FREQUENCY_BAND = 90;
+ /* Enable background scan for configured networks */
+ static final int CMD_ENABLE_BACKGROUND_SCAN = 91;
/* Commands from/to the SupplicantStateTracker */
/* Reset the supplicant state tracker */
@@ -823,6 +827,10 @@ public class WifiStateMachine extends HierarchicalStateMachine {
sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0));
}
+ public void enableBackgroundScan(boolean enabled) {
+ sendMessage(obtainMessage(CMD_ENABLE_BACKGROUND_SCAN, enabled ? 1 : 0, 0));
+ }
+
public void enableAllNetworks() {
sendMessage(CMD_ENABLE_ALL_NETWORKS);
}
@@ -1538,6 +1546,9 @@ public class WifiStateMachine extends HierarchicalStateMachine {
case CMD_ENABLE_RSSI_POLL:
mEnableRssiPolling = (message.arg1 == 1);
break;
+ case CMD_ENABLE_BACKGROUND_SCAN:
+ mEnableBackgroundScan = (message.arg1 == 1);
+ break;
/* Discard */
case CMD_LOAD_DRIVER:
case CMD_UNLOAD_DRIVER:
@@ -1973,6 +1984,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
eventLoggingEnabled = false;
setScanResults(WifiNative.scanResultsCommand());
sendScanResultsAvailableBroadcast();
+ mScanResultIsPending = false;
break;
case CMD_PING_SUPPLICANT:
boolean ok = WifiNative.pingCommand();
@@ -2180,6 +2192,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
case CMD_START_SCAN:
eventLoggingEnabled = false;
WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
+ mScanResultIsPending = true;
break;
case CMD_SET_HIGH_PERF_MODE:
setHighPerfModeEnabledNative(message.arg1 == 1);
@@ -2681,8 +2694,8 @@ public class WifiStateMachine extends HierarchicalStateMachine {
* back to CONNECT_MODE.
*/
WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
- WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
- break;
+ /* Have the parent state handle the rest */
+ return NOT_HANDLED;
/* Ignore connection to same network */
case CMD_CONNECT_NETWORK:
int netId = message.arg1;
@@ -2771,21 +2784,35 @@ public class WifiStateMachine extends HierarchicalStateMachine {
}
class DisconnectedState extends HierarchicalState {
+ private boolean mAlarmEnabled = false;
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- /**
- * In a disconnected state, an infrequent scan that wakes
- * up the device is needed to ensure a user connects to
- * an access point on the move
+ /*
+ * We initiate background scanning if it is enabled, otherwise we
+ * initiate an infrequent scan that wakes up the device to ensure
+ * a user connects to an access point on the move
*/
- long scanMs = Settings.Secure.getLong(mContext.getContentResolver(),
+ if (mEnableBackgroundScan) {
+ /* If a regular scan result is pending, do not initiate background
+ * scan until the scan results are returned. This is needed because
+ * initiating a background scan will cancel the regular scan and
+ * scan results will not be returned until background scanning is
+ * cleared
+ */
+ if (!mScanResultIsPending) {
+ WifiNative.enableBackgroundScan(true);
+ }
+ } else {
+ long scanMs = Settings.Secure.getLong(mContext.getContentResolver(),
Settings.Secure.WIFI_SCAN_INTERVAL_MS, DEFAULT_SCAN_INTERVAL_MS);
- mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
+ mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + scanMs, scanMs, mScanIntent);
+ mAlarmEnabled = true;
+ }
}
@Override
public boolean processMessage(Message message) {
@@ -2800,6 +2827,10 @@ public class WifiStateMachine extends HierarchicalStateMachine {
transitionTo(mScanModeState);
}
break;
+ case CMD_ENABLE_BACKGROUND_SCAN:
+ mEnableBackgroundScan = (message.arg1 == 1);
+ WifiNative.enableBackgroundScan(mEnableBackgroundScan);
+ break;
/* Ignore network disconnect */
case NETWORK_DISCONNECTION_EVENT:
break;
@@ -2808,6 +2839,20 @@ public class WifiStateMachine extends HierarchicalStateMachine {
setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
/* DriverStartedState does the rest of the handling */
return NOT_HANDLED;
+ case CMD_START_SCAN:
+ /* Disable background scan temporarily during a regular scan */
+ if (mEnableBackgroundScan) {
+ WifiNative.enableBackgroundScan(false);
+ }
+ /* Handled in parent state */
+ return NOT_HANDLED;
+ case SCAN_RESULTS_EVENT:
+ /* Re-enable background scan when a pending scan result is received */
+ if (mEnableBackgroundScan && mScanResultIsPending) {
+ WifiNative.enableBackgroundScan(true);
+ }
+ /* Handled in parent state */
+ return NOT_HANDLED;
default:
return NOT_HANDLED;
}
@@ -2817,7 +2862,14 @@ public class WifiStateMachine extends HierarchicalStateMachine {
@Override
public void exit() {
- mAlarmManager.cancel(mScanIntent);
+ /* No need for a background scan upon exit from a disconnected state */
+ if (mEnableBackgroundScan) {
+ WifiNative.enableBackgroundScan(false);
+ }
+ if (mAlarmEnabled) {
+ mAlarmManager.cancel(mScanIntent);
+ mAlarmEnabled = false;
+ }
}
}