summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.xml39
-rwxr-xr-xcore/java/android/animation/ValueAnimator.java4
-rw-r--r--core/java/android/bluetooth/BluetoothDeviceProfileState.java51
-rw-r--r--core/java/android/provider/Settings.java13
-rw-r--r--core/java/android/view/View.java55
-rw-r--r--core/java/android/webkit/WebSettings.java9
-rw-r--r--core/java/android/webkit/ZoomManager.java2
-rw-r--r--core/res/res/values/dimens.xml2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp12
-rw-r--r--libs/hwui/Snapshot.h1
-rw-r--r--policy/src/com/android/internal/policy/impl/StatusView.java16
-rw-r--r--services/java/com/android/server/WindowManagerService.java15
-rw-r--r--voip/java/com/android/server/sip/SipSessionGroup.java8
13 files changed, 104 insertions, 123 deletions
diff --git a/api/current.xml b/api/current.xml
index 5f0824929881..6677a90f9f20 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -204443,19 +204443,6 @@
<parameter name="canvas" type="android.graphics.Canvas">
</parameter>
</method>
-<method name="onDrawDragThumbnail"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="canvas" type="android.graphics.Canvas">
-</parameter>
-</method>
<method name="onDrawScrollBars"
return="void"
abstract="false"
@@ -204649,17 +204636,6 @@
<parameter name="heightMeasureSpec" type="int">
</parameter>
</method>
-<method name="onMeasureDragThumbnail"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-</method>
<method name="onRestoreInstanceState"
return="void"
abstract="false"
@@ -205325,21 +205301,6 @@
<parameter name="contentDescription" type="java.lang.CharSequence">
</parameter>
</method>
-<method name="setDragThumbnailDimension"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="width" type="int">
-</parameter>
-<parameter name="height" type="int">
-</parameter>
-</method>
<method name="setDrawingCacheBackgroundColor"
return="void"
abstract="false"
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 8aa29958a6cc..79754b85e137 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -682,8 +682,8 @@ public class ValueAnimator extends Animator {
// If there are still active or delayed animations, call the handler again
// after the frameDelay
if (callAgain && (!sAnimations.isEmpty() || !sDelayedAnims.isEmpty())) {
- sendEmptyMessageDelayed(ANIMATION_FRAME, Math.max(0, sFrameDelay -
-- (AnimationUtils.currentAnimationTimeMillis() - currentTime)));
+ sendEmptyMessageDelayed(ANIMATION_FRAME, Math.max(0, sFrameDelay -
+ (AnimationUtils.currentAnimationTimeMillis() - currentTime)));
}
break;
}
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index e460839deff0..1c53c45aa3b5 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -75,6 +75,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
public static final int DISCONNECT_A2DP_INCOMING = 53;
public static final int DISCONNECT_HID_OUTGOING = 54;
public static final int DISCONNECT_HID_INCOMING = 55;
+ public static final int DISCONNECT_PBAP_OUTGOING = 56;
public static final int UNPAIR = 100;
public static final int AUTO_CONNECT_PROFILES = 101;
@@ -94,6 +95,8 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
private BluetoothService mService;
private BluetoothA2dpService mA2dpService;
private BluetoothHeadset mHeadsetService;
+ private BluetoothPbap mPbapService;
+ private boolean mPbapServiceConnected;
private BluetoothDevice mDevice;
private int mHeadsetState = BluetoothProfile.STATE_DISCONNECTED;
@@ -201,6 +204,8 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
BluetoothProfile.HEADSET);
+ // TODO(): Convert PBAP to the new Profile APIs.
+ PbapServiceListener p = new PbapServiceListener();
}
private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
@@ -217,6 +222,22 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
}
};
+ private class PbapServiceListener implements BluetoothPbap.ServiceListener {
+ public PbapServiceListener() {
+ mPbapService = new BluetoothPbap(mContext, this);
+ }
+ public void onServiceConnected() {
+ synchronized(BluetoothDeviceProfileState.this) {
+ mPbapServiceConnected = true;
+ }
+ }
+ public void onServiceDisconnected() {
+ synchronized(BluetoothDeviceProfileState.this) {
+ mPbapServiceConnected = false;
+ }
+ }
+ }
+
private class BondedDevice extends HierarchicalState {
@Override
protected void enter() {
@@ -255,6 +276,9 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
case DISCONNECT_HID_INCOMING:
transitionTo(mIncomingHid);
break;
+ case DISCONNECT_PBAP_OUTGOING:
+ processCommand(DISCONNECT_PBAP_OUTGOING);
+ break;
case UNPAIR:
if (mHeadsetState != BluetoothHeadset.STATE_DISCONNECTED) {
sendMessage(DISCONNECT_HFP_OUTGOING);
@@ -404,6 +428,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
deferMessage(deferMsg);
}
break; // ignore
+ case DISCONNECT_PBAP_OUTGOING:
case UNPAIR:
case AUTO_CONNECT_PROFILES:
deferMessage(message);
@@ -478,6 +503,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
case CONNECT_HID_INCOMING:
case DISCONNECT_HID_INCOMING:
break; // ignore
+ case DISCONNECT_PBAP_OUTGOING:
case UNPAIR:
case AUTO_CONNECT_PROFILES:
deferMessage(message);
@@ -582,6 +608,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
deferMessage(deferMsg);
}
break; // ignore
+ case DISCONNECT_PBAP_OUTGOING:
case UNPAIR:
case AUTO_CONNECT_PROFILES:
deferMessage(message);
@@ -654,6 +681,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
case CONNECT_HID_INCOMING:
case DISCONNECT_HID_INCOMING:
break; // ignore
+ case DISCONNECT_PBAP_OUTGOING:
case UNPAIR:
case AUTO_CONNECT_PROFILES:
deferMessage(message);
@@ -734,7 +762,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
case DISCONNECT_HID_INCOMING:
// Ignore, will be handled by Bluez
break;
-
+ case DISCONNECT_PBAP_OUTGOING:
case UNPAIR:
case AUTO_CONNECT_PROFILES:
deferMessage(message);
@@ -792,6 +820,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
case DISCONNECT_A2DP_INCOMING:
// Ignore, will be handled by Bluez
break;
+ case DISCONNECT_PBAP_OUTGOING:
case UNPAIR:
case AUTO_CONNECT_PROFILES:
deferMessage(message);
@@ -818,7 +847,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
}
}
- synchronized void deferHeadsetMessage(int command) {
+ synchronized void deferProfileServiceMessage(int command) {
Message msg = new Message();
msg.what = command;
deferMessage(msg);
@@ -829,14 +858,14 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
switch(command) {
case CONNECT_HFP_OUTGOING:
if (mHeadsetService == null) {
- deferHeadsetMessage(command);
+ deferProfileServiceMessage(command);
} else {
return mHeadsetService.connectHeadsetInternal(mDevice);
}
break;
case CONNECT_HFP_INCOMING:
if (mHeadsetService == null) {
- deferHeadsetMessage(command);
+ deferProfileServiceMessage(command);
} else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
return mHeadsetService.acceptIncomingConnect(mDevice);
} else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
@@ -857,8 +886,13 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
return true;
case DISCONNECT_HFP_OUTGOING:
if (mHeadsetService == null) {
- deferHeadsetMessage(command);
+ deferProfileServiceMessage(command);
} else {
+ // Disconnect PBAP
+ // TODO(): Add PBAP to the state machine.
+ Message m = new Message();
+ m.what = DISCONNECT_PBAP_OUTGOING;
+ deferMessage(m);
if (mHeadsetService.getPriority(mDevice) ==
BluetoothHeadset.PRIORITY_AUTO_CONNECT) {
mHeadsetService.setPriority(mDevice, BluetoothHeadset.PRIORITY_ON);
@@ -890,6 +924,13 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
mService.setInputDevicePriority(mDevice, BluetoothInputDevice.PRIORITY_ON);
}
return mService.disconnectInputDeviceInternal(mDevice);
+ case DISCONNECT_PBAP_OUTGOING:
+ if (!mPbapServiceConnected) {
+ deferProfileServiceMessage(command);
+ } else {
+ return mPbapService.disconnect();
+ }
+ break;
case UNPAIR:
return mService.removeBondInternal(mDevice.getAddress());
default:
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cf95872a72fa..56babdd20deb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2553,6 +2553,19 @@ public final class Settings {
/**
+ * This preference contains the string that shows for owner info on LockScren.
+ * @hide
+ */
+ public static final String LOCK_SCREEN_OWNER_INFO = "lock_screen_owner_info";
+
+ /**
+ * This preference enables showing the owner info on LockScren.
+ * @hide
+ */
+ public static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
+ "lock_screen_owner_info_enabled";
+
+ /**
* Whether assisted GPS should be enabled or not.
* @hide
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7ee360d59268..8e4591aac047 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2037,8 +2037,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*
*/
boolean mCanAcceptDrop;
- private int mThumbnailWidth;
- private int mThumbnailHeight;
/**
* Simple constructor to use when creating a view from code.
@@ -9921,10 +9919,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
throw new IllegalStateException("Drag thumb dimensions must not be negative");
}
+ if (ViewDebug.DEBUG_DRAG) {
+ Log.d(VIEW_LOG_TAG, "drag thumb: width=" + thumbSize.x + " height=" + thumbSize.y
+ + " thumbX=" + thumbTouchPoint.x + " thumbY=" + thumbTouchPoint.y);
+ }
Surface surface = new Surface();
try {
IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
- myWindowOnly, mThumbnailWidth, mThumbnailHeight, surface);
+ myWindowOnly, thumbSize.x, thumbSize.y, surface);
if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
+ " surface=" + surface);
if (token != null) {
@@ -9951,53 +9953,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return okay;
}
- private void measureThumbnail() {
- mPrivateFlags &= ~MEASURED_DIMENSION_SET;
-
- onMeasureDragThumbnail();
-
- // flag not set, setDragThumbnailDimension() was not invoked, we raise
- // an exception to warn the developer
- if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
- throw new IllegalStateException("onMeasureDragThumbnail() did not set the"
- + " measured dimension by calling setDragThumbnailDimension()");
- }
-
- if (ViewDebug.DEBUG_DRAG) {
- Log.d(VIEW_LOG_TAG, "Drag thumb measured: w=" + mThumbnailWidth
- + " h=" + mThumbnailHeight);
- }
- }
-
- /**
- * The View must call this method from onMeasureDragThumbnail() in order to
- * specify the dimensions of the drag thumbnail image.
- *
- * @param width The desired thumbnail width.
- * @param height The desired thumbnail height.
- */
- protected final void setDragThumbnailDimension(int width, int height) {
- mPrivateFlags |= MEASURED_DIMENSION_SET;
- mThumbnailWidth = width;
- mThumbnailHeight = height;
- }
-
- /**
- * The default implementation specifies a drag thumbnail that matches the
- * View's current size and appearance.
- */
- protected void onMeasureDragThumbnail() {
- setDragThumbnailDimension(getWidth(), getHeight());
- }
-
- /**
- * The default implementation just draws the current View appearance as the thumbnail
- * @param canvas
- */
- protected void onDrawDragThumbnail(Canvas canvas) {
- draw(canvas);
- }
-
/**
* Drag-and-drop event dispatch. The event.getAction() verb is one of the DragEvent
* constants DRAG_STARTED_EVENT, DRAG_EVENT, DROP_EVENT, and DRAG_ENDED_EVENT.
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 4689740b869c..1dd2e8f4f0c3 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -179,7 +179,6 @@ public class WebSettings {
private boolean mUseDoubleTree = false;
private boolean mUseWideViewport = false;
private boolean mUseFixedViewport = false;
- private int mMaxFixedViewportWidth = WebView.DEFAULT_VIEWPORT_WIDTH;
private boolean mSupportMultipleWindows = false;
private boolean mShrinksStandaloneImagesToFit = false;
private long mMaximumDecodedImageSize = 0; // 0 means default
@@ -378,7 +377,6 @@ public class WebSettings {
final int minTabletWidth = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.min_xlarge_screen_width);
mUseFixedViewport = (metrics.density == 1.0f && landscapeWidth >= minTabletWidth);
- mMaxFixedViewportWidth = (int) (landscapeWidth * 1.25);
if (sLockForLocaleSettings == null) {
sLockForLocaleSettings = new Object();
@@ -1570,13 +1568,6 @@ public class WebSettings {
}
/**
- * Returns maximum fixed viewport width.
- */
- /* package */ int getMaxFixedViewportWidth() {
- return mMaxFixedViewportWidth;
- }
-
- /**
* Returns whether private browsing is enabled.
*/
/* package */ boolean isPrivateBrowsingEnabled() {
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index b46cec7c7830..b0a96be9987d 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -844,7 +844,7 @@ class ZoomManager {
if (mInitialScale > 0) {
scale = mInitialScale;
reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale);
- } else if (viewState.mViewScale > 0 &&
+ } else if (viewState.mViewScale > 0 &&
(viewState.mMobileSite || !settings.getUseFixedViewport())) {
mTextWrapScale = viewState.mTextWrapScale;
scale = viewState.mViewScale;
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 6ec80174b3ac..0928ce051279 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -46,8 +46,6 @@
<dimen name="fastscroll_thumb_height">52dp</dimen>
<!-- Min width for a tablet device -->
<dimen name="min_xlarge_screen_width">800dp</dimen>
- <!-- Fixed viewport margin for website content width change -->
- <dimen name="fixed_viewport_margin">7dp</dimen>
<!-- Default height of a key in the password keyboard for alpha -->
<dimen name="password_keyboard_key_height_alpha">56dip</dimen>
<!-- Default height of a key in the password keyboard for numeric -->
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 287601092f20..81fa1ea521b2 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -388,7 +388,8 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
snapshot->invisible = true;
} else {
// TODO: Should take the mode into account
- snapshot->invisible = snapshot->previous->invisible || alpha <= ALPHA_THRESHOLD;
+ snapshot->invisible = snapshot->previous->invisible ||
+ (alpha <= ALPHA_THRESHOLD && fboLayer);
}
// Bail out if we won't draw in this snapshot
@@ -551,7 +552,7 @@ void OpenGLRenderer::clearLayerRegions() {
Rect* bounds = mLayers.itemAt(i);
// Clear the framebuffer where the layer will draw
- glScissor(bounds->left, mHeight - bounds->bottom,
+ glScissor(bounds->left, mSnapshot->height - bounds->bottom,
bounds->getWidth(), bounds->getHeight());
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
@@ -620,7 +621,12 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto
Rect r(left, top, right, bottom);
mSnapshot->transform->mapRect(r);
- return !mSnapshot->clipRect->intersects(r);
+ r.snapToPixelBoundaries();
+
+ Rect clipRect(*mSnapshot->clipRect);
+ clipRect.snapToPixelBoundaries();
+
+ return !clipRect.intersects(r);
}
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 35cdf6f23395..2da195016c3a 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -152,7 +152,6 @@ public:
}
if (clipped) {
- clipRect->snapToPixelBoundaries();
flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip;
}
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
index 3f08cfd841a0..2b788514df70 100644
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ b/policy/src/com/android/internal/policy/impl/StatusView.java
@@ -4,11 +4,14 @@ package com.android.internal.policy.impl;
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
+import com.google.android.util.AbstractMessageParser.Resources;
import java.util.Date;
+import android.content.ContentResolver;
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Log;
@@ -138,11 +141,14 @@ class StatusView {
/** Originated from PatternUnlockScreen **/
void updateStatusLines() {
if (mHasProperty) {
- // TODO Get actual name & email
- String name = "John Smith";
- String email = "jsmith@gmail.com";
- mPropertyOf.setText("Property of:\n" + name + "\n" + email);
- mPropertyOf.setVisibility(View.VISIBLE);
+ ContentResolver res = getContext().getContentResolver();
+ String info = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
+ boolean enabled = Settings.Secure.getInt(res,
+ Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
+
+ mPropertyOf.setText(info);
+ mPropertyOf.setVisibility(enabled && !TextUtils.isEmpty(info) ?
+ View.VISIBLE : View.INVISIBLE);
}
if (!mHasStatus2) return;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 6c23e3765421..def36de4f22b 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -555,6 +555,12 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ int getDragLayerLw() {
+ return mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
+ * TYPE_LAYER_MULTIPLIER
+ + TYPE_LAYER_OFFSET;
+ }
+
/* call out to each visible window/session informing it about the drag
*/
void broadcastDragStartedLw(final float touchX, final float touchY) {
@@ -5533,7 +5539,7 @@ public class WindowManagerService extends IWindowManager.Stub
return null;
}
- private void addDragInputWindow(InputWindowList windowList) {
+ private void addDragInputWindowLw(InputWindowList windowList) {
final InputWindow inputWindow = windowList.add();
inputWindow.inputChannel = mDragState.mServerChannel;
inputWindow.name = "drag";
@@ -5545,9 +5551,7 @@ public class WindowManagerService extends IWindowManager.Stub
inputWindow.hasFocus = true;
inputWindow.hasWallpaper = false;
inputWindow.paused = false;
- inputWindow.layer = mPolicy.windowTypeToLayerLw(inputWindow.layoutParamsType)
- * TYPE_LAYER_MULTIPLIER
- + TYPE_LAYER_OFFSET;
+ inputWindow.layer = mDragState.getDragLayerLw();
inputWindow.ownerPid = Process.myPid();
inputWindow.ownerUid = Process.myUid();
@@ -5583,7 +5587,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_DRAG) {
Log.d(TAG, "Inserting drag window");
}
- addDragInputWindow(mTempInputWindows);
+ addDragInputWindowLw(mTempInputWindows);
}
final int N = windows.size();
@@ -6231,6 +6235,7 @@ public class WindowManagerService extends IWindowManager.Stub
surface.setPosition((int)(touchX - thumbCenterX),
(int)(touchY - thumbCenterY));
surface.setAlpha(.5f);
+ surface.setLayer(mDragState.getDragLayerLw());
surface.show();
} finally {
surface.closeTransaction();
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 57b3710cf30d..b5f8d39c6edb 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -153,7 +153,13 @@ class SipSessionGroup implements SipListener {
}
synchronized void onConnectivityChanged() {
- for (SipSessionImpl s : mSessionMap.values()) {
+ SipSessionImpl[] ss = mSessionMap.values().toArray(
+ new SipSessionImpl[mSessionMap.size()]);
+ // Iterate on the copied array instead of directly on mSessionMap to
+ // avoid ConcurrentModificationException being thrown when
+ // SipSessionImpl removes itself from mSessionMap in onError() in the
+ // following loop.
+ for (SipSessionImpl s : ss) {
s.onError(SipErrorCode.DATA_CONNECTION_LOST,
"data connection lost");
}