Merge "Update ScriptC constructor to remove depricated param."
diff --git a/api/current.xml b/api/current.xml
index d682155..0cf46eb 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1905,7 +1905,7 @@
type="int"
transient="false"
volatile="false"
- value="16843550"
+ value="16843552"
static="true"
final="true"
deprecated="not deprecated"
@@ -1916,7 +1916,7 @@
type="int"
transient="false"
volatile="false"
- value="16843549"
+ value="16843551"
static="true"
final="true"
deprecated="not deprecated"
@@ -1927,7 +1927,7 @@
type="int"
transient="false"
volatile="false"
- value="16843551"
+ value="16843553"
static="true"
final="true"
deprecated="not deprecated"
@@ -3804,6 +3804,17 @@
visibility="public"
>
</field>
+<field name="enterFadeDuration"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843549"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="entries"
type="int"
transient="false"
@@ -3848,6 +3859,17 @@
visibility="public"
>
</field>
+<field name="exitFadeDuration"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843550"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="expandableListPreferredChildIndicatorLeft"
type="int"
transient="false"
@@ -9308,7 +9330,7 @@
type="int"
transient="false"
volatile="false"
- value="16843553"
+ value="16843555"
static="true"
final="true"
deprecated="not deprecated"
@@ -9319,7 +9341,7 @@
type="int"
transient="false"
volatile="false"
- value="16843552"
+ value="16843554"
static="true"
final="true"
deprecated="not deprecated"
@@ -19503,6 +19525,17 @@
<parameter name="index" type="int">
</parameter>
</method>
+<method name="getTabCount"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getTitle"
return="java.lang.CharSequence"
abstract="true"
@@ -28300,6 +28333,17 @@
visibility="public"
>
</method>
+<method name="disallowAddToBackStack"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="hide"
return="android.app.FragmentTransaction"
abstract="true"
@@ -28313,6 +28357,17 @@
<parameter name="fragment" type="android.app.Fragment">
</parameter>
</method>
+<method name="isAddToBackStackAllowed"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="isEmpty"
return="boolean"
abstract="true"
@@ -83932,6 +83987,17 @@
visibility="public"
>
</method>
+<method name="jumpToCurrentState"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="mutate"
return="android.graphics.drawable.Drawable"
abstract="false"
@@ -84421,6 +84487,32 @@
<parameter name="state" type="android.graphics.drawable.DrawableContainer.DrawableContainerState">
</parameter>
</method>
+<method name="setEnterFadeDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ms" type="int">
+</parameter>
+</method>
+<method name="setExitFadeDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ms" type="int">
+</parameter>
+</method>
<method name="unscheduleDrawable"
return="void"
abstract="false"
@@ -84568,6 +84660,28 @@
visibility="public"
>
</method>
+<method name="getEnterFadeDuration"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExitFadeDuration"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getOpacity"
return="int"
abstract="false"
@@ -84629,6 +84743,32 @@
<parameter name="constant" type="boolean">
</parameter>
</method>
+<method name="setEnterFadeDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="int">
+</parameter>
+</method>
+<method name="setExitFadeDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="int">
+</parameter>
+</method>
<method name="setVariablePadding"
return="void"
abstract="false"
@@ -190423,6 +190563,17 @@
<parameter name="newSize" type="int">
</parameter>
</method>
+<field name="NOTHING"
+ type="int[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="WILD_CARD"
type="int[]"
transient="false"
@@ -203765,6 +203916,17 @@
visibility="public"
>
</method>
+<method name="jumpDrawablesToCurrentState"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="layout"
return="void"
abstract="false"
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 39754b0..1945b05 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -665,6 +665,11 @@
public IntPropertyValuesHolder(String propertyName, int... values) {
super(propertyName);
setIntValues(values);
+ }
+
+ @Override
+ public void setIntValues(int... values) {
+ super.setIntValues(values);
mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet;
}
@@ -722,6 +727,11 @@
public FloatPropertyValuesHolder(String propertyName, float... values) {
super(propertyName);
setFloatValues(values);
+ }
+
+ @Override
+ public void setFloatValues(float... values) {
+ super.setFloatValues(values);
mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet;
}
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index e185624..a57b54a 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -478,6 +478,12 @@
public abstract Tab getTabAt(int index);
/**
+ * Returns the number of tabs currently registered with the action bar.
+ * @return Tab count
+ */
+ public abstract int getTabCount();
+
+ /**
* Retrieve the current height of the ActionBar.
*
* @return The ActionBar's height
@@ -626,7 +632,8 @@
* @param tab The tab that was selected
* @param ft A {@link FragmentTransaction} for queuing fragment operations to execute
* during a tab switch. The previous tab's unselect and this tab's select will be
- * executed in a single transaction.
+ * executed in a single transaction. This FragmentTransaction does not support
+ * being added to the back stack.
*/
public void onTabSelected(Tab tab, FragmentTransaction ft);
@@ -636,7 +643,8 @@
* @param tab The tab that was unselected
* @param ft A {@link FragmentTransaction} for queuing fragment operations to execute
* during a tab switch. This tab's unselect and the newly selected tab's select
- * will be executed in a single transaction.
+ * will be executed in a single transaction. This FragmentTransaction does not
+ * support being added to the back stack.
*/
public void onTabUnselected(Tab tab, FragmentTransaction ft);
@@ -646,7 +654,8 @@
*
* @param tab The tab that was reselected.
* @param ft A {@link FragmentTransaction} for queuing fragment operations to execute
- * once this method returns.
+ * once this method returns. This FragmentTransaction does not support
+ * being added to the back stack.
*/
public void onTabReselected(Tab tab, FragmentTransaction ft);
}
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index e6cc0f9..c75777d 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -186,6 +186,7 @@
int mTransition;
int mTransitionStyle;
boolean mAddToBackStack;
+ boolean mAllowAddToBackStack = true;
String mName;
boolean mCommitted;
int mIndex;
@@ -346,11 +347,28 @@
}
public FragmentTransaction addToBackStack(String name) {
+ if (!mAllowAddToBackStack) {
+ throw new IllegalStateException(
+ "This FragmentTransaction is not allowed to be added to the back stack.");
+ }
mAddToBackStack = true;
mName = name;
return this;
}
+ public boolean isAddToBackStackAllowed() {
+ return mAllowAddToBackStack;
+ }
+
+ public FragmentTransaction disallowAddToBackStack() {
+ if (mAddToBackStack) {
+ throw new IllegalStateException(
+ "This transaction is already being added to the back stack");
+ }
+ mAllowAddToBackStack = false;
+ return this;
+ }
+
public FragmentTransaction setBreadCrumbTitle(int res) {
mBreadCrumbTitleRes = res;
mBreadCrumbTitleText = null;
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index b00476bb..19da763 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -144,6 +144,22 @@
public FragmentTransaction addToBackStack(String name);
/**
+ * Returns true if this FragmentTransaction is allowed to be added to the back
+ * stack. If this method would return false, {@link #addToBackStack(String)}
+ * will throw {@link IllegalStateException}.
+ *
+ * @return True if {@link #addToBackStack(String)} is permitted on this transaction.
+ */
+ public boolean isAddToBackStackAllowed();
+
+ /**
+ * Disallow calls to {@link #addToBackStack(String)}. Any future calls to
+ * addToBackStack will throw {@link IllegalStateException}. If addToBackStack
+ * has already been called, this method will throw IllegalStateException.
+ */
+ public FragmentTransaction disallowAddToBackStack();
+
+ /**
* Set the full title to show as a bread crumb when this transaction
* is on the back stack, as used by {@link FragmentBreadCrumbs}.
*
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 7743ceb..cd08e33 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -39,8 +39,6 @@
// NfcAdapter-class related methods
boolean isEnabled();
- NdefMessage localGet();
- void localSet(in NdefMessage message);
void openTagConnection(in Tag tag);
// Non-public methods
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index cf80faf..88b6ea4 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -301,48 +301,6 @@
}
/**
- * Set the NDEF Message that this NFC adapter should appear as to Tag
- * readers.
- * <p>
- * Any Tag reader can read the contents of the local tag when it is in
- * proximity, without any further user confirmation.
- * <p>
- * The implementation of this method must either
- * <ul>
- * <li>act as a passive tag containing this NDEF message
- * <li>provide the NDEF message on over LLCP to peer NFC adapters
- * </ul>
- * The NDEF message is preserved across reboot.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- *
- * @param message NDEF message to make public
- * @hide
- */
- public void setLocalNdefMessage(NdefMessage message) {
- try {
- mService.localSet(message);
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- }
- }
-
- /**
- * Get the NDEF Message that this adapter appears as to Tag readers.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- *
- * @return NDEF Message that is publicly readable
- * @hide
- */
- public NdefMessage getLocalNdefMessage() {
- try {
- return mService.localGet();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return null;
- }
- }
-
- /**
* Create a raw tag connection to the default Target
* <p>Requires {@link android.Manifest.permission#NFC} permission.
* @hide
diff --git a/core/java/android/util/StateSet.java b/core/java/android/util/StateSet.java
index f3d8159..21d8e45 100644
--- a/core/java/android/util/StateSet.java
+++ b/core/java/android/util/StateSet.java
@@ -38,6 +38,7 @@
public class StateSet {
public static final int[] WILD_CARD = new int[0];
+ public static final int[] NOTHING = new int[] { 0 };
/**
* Return whether the stateSetOrSpec is matched by all StateSets.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7276044..340678d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8620,6 +8620,16 @@
}
/**
+ * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
+ * on all Drawable objects associated with this view.
+ */
+ public void jumpDrawablesToCurrentState() {
+ if (mBGDrawable != null) {
+ mBGDrawable.jumpToCurrentState();
+ }
+ }
+
+ /**
* Sets the background color for this view.
* @param color the color of the background
*/
@@ -8627,6 +8637,7 @@
public void setBackgroundColor(int color) {
if (mBGDrawable instanceof ColorDrawable) {
((ColorDrawable) mBGDrawable).setColor(color);
+ invalidate();
} else {
setBackgroundDrawable(new ColorDrawable(color));
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 4e90ecd..7629673 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -36,6 +36,7 @@
import android.util.Log;
import android.util.LongSparseArray;
import android.util.SparseBooleanArray;
+import android.util.StateSet;
import android.view.ActionMode;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
@@ -254,6 +255,17 @@
Drawable mSelector;
/**
+ * Set to true if we would like to have the selector showing itself.
+ * We still need to draw and position it even if this is false.
+ */
+ boolean mSelectorShowing;
+
+ /**
+ * The current position of the selector in the list.
+ */
+ int mSelectorPosition = INVALID_POSITION;
+
+ /**
* Defines the selector's location and dimension at drawing time
*/
Rect mSelectorRect = new Rect();
@@ -1324,6 +1336,7 @@
setSelectedPositionInt(INVALID_POSITION);
// Do this before setting mNeedSync since setNextSelectedPosition looks at mNeedSync
setNextSelectedPositionInt(INVALID_POSITION);
+ mSelectorPosition = INVALID_POSITION;
mNeedSync = true;
mSyncRowId = ss.firstId;
mSyncPosition = ss.position;
@@ -1416,6 +1429,8 @@
setSelectedPositionInt(INVALID_POSITION);
setNextSelectedPositionInt(INVALID_POSITION);
mSelectedTop = 0;
+ mSelectorShowing = false;
+ mSelectorPosition = INVALID_POSITION;
mSelectorRect.setEmpty();
invalidate();
}
@@ -1708,7 +1723,7 @@
}
if (child != scrapView) {
- mRecycler.addScrapView(scrapView);
+ mRecycler.addScrapView(scrapView, position);
if (mCacheColorHint != 0) {
child.setDrawingCacheBackgroundColor(mCacheColorHint);
}
@@ -1734,7 +1749,11 @@
return child;
}
- void positionSelector(View sel) {
+ void positionSelector(int position, View sel) {
+ if (position != INVALID_POSITION) {
+ mSelectorPosition = position;
+ }
+
final Rect selectorRect = mSelectorRect;
selectorRect.set(sel.getLeft(), sel.getTop(), sel.getRight(), sel.getBottom());
positionSelector(selectorRect.left, selectorRect.top, selectorRect.right,
@@ -1743,7 +1762,9 @@
final boolean isChildViewEnabled = mIsChildViewEnabled;
if (sel.isEnabled() != isChildViewEnabled) {
mIsChildViewEnabled = !isChildViewEnabled;
- refreshDrawableState();
+ if (mSelectorShowing) {
+ refreshDrawableState();
+ }
}
}
@@ -1822,7 +1843,7 @@
}
private void drawSelector(Canvas canvas) {
- if (shouldShowSelector() && mSelectorRect != null && !mSelectorRect.isEmpty()) {
+ if (!mSelectorRect.isEmpty()) {
final Drawable selector = mSelector;
selector.setBounds(mSelectorRect);
selector.draw(canvas);
@@ -1866,7 +1887,7 @@
mSelectionRightPadding = padding.right;
mSelectionBottomPadding = padding.bottom;
sel.setCallback(this);
- sel.setState(getDrawableState());
+ updateSelectorState();
}
/**
@@ -1891,7 +1912,7 @@
Drawable selector = mSelector;
Rect selectorRect = mSelectorRect;
if (selector != null && (isFocused() || touchModeDrawsInPressedState())
- && selectorRect != null && !selectorRect.isEmpty()) {
+ && !selectorRect.isEmpty()) {
final View v = getChildAt(mSelectedPosition - mFirstPosition);
@@ -1926,12 +1947,20 @@
mScrollDown = down;
}
+ void updateSelectorState() {
+ if (mSelector != null) {
+ if (shouldShowSelector()) {
+ mSelector.setState(getDrawableState());
+ } else {
+ mSelector.setState(StateSet.NOTHING);
+ }
+ }
+ }
+
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
- if (mSelector != null) {
- mSelector.setState(getDrawableState());
- }
+ updateSelectorState();
}
@Override
@@ -2141,7 +2170,6 @@
} else {
mTouchMode = TOUCH_MODE_DONE_WAITING;
}
-
}
}
}
@@ -2316,10 +2344,10 @@
mLayoutMode = LAYOUT_NORMAL;
if (!mDataChanged) {
- layoutChildren();
child.setPressed(true);
- positionSelector(child);
setPressed(true);
+ layoutChildren();
+ positionSelector(mMotionPosition, child);
final int longPressTimeout = ViewConfiguration.getLongPressTimeout();
final boolean longClickable = isLongClickable();
@@ -2566,7 +2594,7 @@
setSelectedPositionInt(mMotionPosition);
layoutChildren();
child.setPressed(true);
- positionSelector(child);
+ positionSelector(mMotionPosition, child);
setPressed(true);
if (mSelector != null) {
Drawable d = mSelector.getCurrent();
@@ -2576,16 +2604,17 @@
}
postDelayed(new Runnable() {
public void run() {
+ mTouchMode = TOUCH_MODE_REST;
child.setPressed(false);
setPressed(false);
if (!mDataChanged) {
post(performClick);
}
- mTouchMode = TOUCH_MODE_REST;
}
}, ViewConfiguration.getPressedStateDuration());
} else {
mTouchMode = TOUCH_MODE_REST;
+ updateSelectorState();
}
return true;
} else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
@@ -2593,6 +2622,7 @@
}
}
mTouchMode = TOUCH_MODE_REST;
+ updateSelectorState();
break;
case TOUCH_MODE_SCROLL:
final int childCount = getChildCount();
@@ -3507,7 +3537,7 @@
count++;
int position = firstPosition + i;
if (position >= headerViewsCount && position < footerViewsStart) {
- mRecycler.addScrapView(child);
+ mRecycler.addScrapView(child, position);
if (ViewDebug.TRACE_RECYCLER) {
ViewDebug.trace(child,
@@ -3528,7 +3558,7 @@
count++;
int position = firstPosition + i;
if (position >= headerViewsCount && position < footerViewsStart) {
- mRecycler.addScrapView(child);
+ mRecycler.addScrapView(child, position);
if (ViewDebug.TRACE_RECYCLER) {
ViewDebug.trace(child,
@@ -3563,8 +3593,15 @@
if (!inTouchMode && mSelectedPosition != INVALID_POSITION) {
final int childIndex = mSelectedPosition - mFirstPosition;
if (childIndex >= 0 && childIndex < getChildCount()) {
- positionSelector(getChildAt(childIndex));
+ positionSelector(mSelectedPosition, getChildAt(childIndex));
}
+ } else if (mSelectorPosition != INVALID_POSITION) {
+ final int childIndex = mSelectorPosition - mFirstPosition;
+ if (childIndex >= 0 && childIndex < getChildCount()) {
+ positionSelector(INVALID_POSITION, getChildAt(childIndex));
+ }
+ } else {
+ mSelectorRect.setEmpty();
}
mBlockLayoutRequests = false;
@@ -3616,7 +3653,7 @@
setSelectedPositionInt(INVALID_POSITION);
setNextSelectedPositionInt(INVALID_POSITION);
mSelectedTop = 0;
- mSelectorRect.setEmpty();
+ mSelectorShowing = false;
}
}
@@ -3876,6 +3913,7 @@
mNextSelectedPosition = INVALID_POSITION;
mNextSelectedRowId = INVALID_ROW_ID;
mNeedSync = false;
+ mSelectorPosition = INVALID_POSITION;
checkSelectionChanged();
}
@@ -4562,6 +4600,13 @@
@ViewDebug.ExportedProperty(category = "list")
boolean forceAdd;
+ /**
+ * The position the view was removed from when pulled out of the
+ * scrap heap.
+ * @hide
+ */
+ int scrappedFromPosition;
+
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
@@ -4741,23 +4786,12 @@
* @return A view from the ScrapViews collection. These are unordered.
*/
View getScrapView(int position) {
- ArrayList<View> scrapViews;
if (mViewTypeCount == 1) {
- scrapViews = mCurrentScrap;
- int size = scrapViews.size();
- if (size > 0) {
- return scrapViews.remove(size - 1);
- } else {
- return null;
- }
+ return retrieveFromScrap(mCurrentScrap, position);
} else {
int whichScrap = mAdapter.getItemViewType(position);
if (whichScrap >= 0 && whichScrap < mScrapViews.length) {
- scrapViews = mScrapViews[whichScrap];
- int size = scrapViews.size();
- if (size > 0) {
- return scrapViews.remove(size - 1);
- }
+ return retrieveFromScrap(mScrapViews[whichScrap], position);
}
}
return null;
@@ -4768,7 +4802,7 @@
*
* @param scrap The view to add
*/
- void addScrapView(View scrap) {
+ void addScrapView(View scrap, int position) {
AbsListView.LayoutParams lp = (AbsListView.LayoutParams) scrap.getLayoutParams();
if (lp == null) {
return;
@@ -4784,6 +4818,8 @@
return;
}
+ lp.scrappedFromPosition = position;
+
if (mViewTypeCount == 1) {
scrap.dispatchStartTemporaryDetach();
mCurrentScrap.add(scrap);
@@ -4810,7 +4846,9 @@
for (int i = count - 1; i >= 0; i--) {
final View victim = activeViews[i];
if (victim != null) {
- int whichScrap = ((AbsListView.LayoutParams) victim.getLayoutParams()).viewType;
+ final AbsListView.LayoutParams lp
+ = (AbsListView.LayoutParams) victim.getLayoutParams();
+ int whichScrap = lp.viewType;
activeViews[i] = null;
@@ -4826,6 +4864,7 @@
scrapViews = mScrapViews[whichScrap];
}
victim.dispatchStartTemporaryDetach();
+ lp.scrappedFromPosition = mFirstActivePosition + i;
scrapViews.add(victim);
if (hasListener) {
@@ -4911,4 +4950,22 @@
}
}
}
+
+ static View retrieveFromScrap(ArrayList<View> scrapViews, int position) {
+ int size = scrapViews.size();
+ if (size > 0) {
+ // See if we still have a view for this position.
+ for (int i=0; i<size; i++) {
+ View view = scrapViews.get(i);
+ if (((AbsListView.LayoutParams)view.getLayoutParams())
+ .scrappedFromPosition == position) {
+ scrapViews.remove(i);
+ return view;
+ }
+ }
+ return scrapViews.remove(size - 1);
+ } else {
+ return null;
+ }
+ }
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index f5afb94..f16efbd 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.database.DataSetObserver;
-import android.os.Handler;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 46c7d33..936a97d 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1009,7 +1009,7 @@
childHeight = child.getMeasuredHeight();
if (mRecycler.shouldRecycleViewType(p.viewType)) {
- mRecycler.addScrapView(child);
+ mRecycler.addScrapView(child, -1);
}
}
@@ -1148,7 +1148,7 @@
if (dataChanged) {
for (int i = 0; i < childCount; i++) {
- recycleBin.addScrapView(getChildAt(i));
+ recycleBin.addScrapView(getChildAt(i), firstPosition+i);
}
} else {
recycleBin.fillActiveViews(childCount, firstPosition);
@@ -1215,11 +1215,11 @@
recycleBin.scrapActiveViews();
if (sel != null) {
- positionSelector(sel);
+ positionSelector(INVALID_POSITION, sel);
mSelectedTop = sel.getTop();
} else if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) {
View child = getChildAt(mMotionPosition - mFirstPosition);
- if (child != null) positionSelector(child);
+ if (child != null) positionSelector(mMotionPosition, child);
} else {
mSelectedTop = 0;
mSelectorRect.setEmpty();
@@ -1391,6 +1391,11 @@
if (mCachingStarted) {
child.setDrawingCacheEnabled(true);
}
+
+ if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition)
+ != position) {
+ child.jumpDrawablesToCurrentState();
+ }
}
/**
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index b5e103f..e0119e9 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -581,7 +581,7 @@
final boolean scroll = scrollYDelta != 0;
if (scroll) {
scrollListItemsBy(-scrollYDelta);
- positionSelector(child);
+ positionSelector(INVALID_POSITION, child);
mSelectedTop = child.getTop();
invalidate();
}
@@ -1086,7 +1086,7 @@
if (recycleOnMeasure() && mRecycler.shouldRecycleViewType(
((LayoutParams) child.getLayoutParams()).viewType)) {
- mRecycler.addScrapView(child);
+ mRecycler.addScrapView(child, -1);
}
}
@@ -1203,7 +1203,7 @@
// Recycle the view before we possibly return from the method
if (recyle && recycleBin.shouldRecycleViewType(
((LayoutParams) child.getLayoutParams()).viewType)) {
- recycleBin.addScrapView(child);
+ recycleBin.addScrapView(child, -1);
}
returnedHeight += child.getMeasuredHeight();
@@ -1507,7 +1507,7 @@
// already cached in mHeaderViews;
if (dataChanged) {
for (int i = 0; i < childCount; i++) {
- recycleBin.addScrapView(getChildAt(i));
+ recycleBin.addScrapView(getChildAt(i), firstPosition+i);
if (ViewDebug.TRACE_RECYCLER) {
ViewDebug.trace(getChildAt(i),
ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, index, i);
@@ -1610,19 +1610,19 @@
if (focused != null) {
focused.clearFocus();
}
- positionSelector(sel);
+ positionSelector(INVALID_POSITION, sel);
} else {
sel.setSelected(false);
mSelectorRect.setEmpty();
}
} else {
- positionSelector(sel);
+ positionSelector(INVALID_POSITION, sel);
}
mSelectedTop = sel.getTop();
} else {
if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) {
View child = getChildAt(mMotionPosition - mFirstPosition);
- if (child != null) positionSelector(child);
+ if (child != null) positionSelector(mMotionPosition, child);
} else {
mSelectedTop = 0;
mSelectorRect.setEmpty();
@@ -1703,7 +1703,7 @@
if (!mDataChanged) {
- // Try to use an exsiting view for this position
+ // Try to use an existing view for this position
child = mRecycler.getActiveView(position);
if (child != null) {
if (ViewDebug.TRACE_RECYCLER) {
@@ -1820,6 +1820,11 @@
if (mCachingStarted && !child.isDrawingCacheEnabled()) {
child.setDrawingCacheEnabled(true);
}
+
+ if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition)
+ != position) {
+ child.jumpDrawablesToCurrentState();
+ }
}
@Override
@@ -2288,6 +2293,7 @@
}
View selectedView = getSelectedView();
+ int selectedPos = mSelectedPosition;
int nextSelectedPosition = lookForSelectablePositionOnScreen(direction);
int amountToScroll = amountToScroll(direction, nextSelectedPosition);
@@ -2305,6 +2311,7 @@
setSelectedPositionInt(nextSelectedPosition);
setNextSelectedPositionInt(nextSelectedPosition);
selectedView = getSelectedView();
+ selectedPos = nextSelectedPosition;
if (mItemsCanFocus && focusResult == null) {
// there was no new view found to take focus, make sure we
// don't leave focus with the old selection
@@ -2345,7 +2352,7 @@
if (needToRedraw) {
if (selectedView != null) {
- positionSelector(selectedView);
+ positionSelector(selectedPos, selectedView);
mSelectedTop = selectedView.getTop();
}
if (!awakenScrollBars()) {
@@ -2841,7 +2848,7 @@
AbsListView.LayoutParams layoutParams = (LayoutParams) first.getLayoutParams();
if (recycleBin.shouldRecycleViewType(layoutParams.viewType)) {
detachViewFromParent(first);
- recycleBin.addScrapView(first);
+ recycleBin.addScrapView(first, mFirstPosition);
} else {
removeViewInLayout(first);
}
@@ -2872,7 +2879,7 @@
AbsListView.LayoutParams layoutParams = (LayoutParams) last.getLayoutParams();
if (recycleBin.shouldRecycleViewType(layoutParams.viewType)) {
detachViewFromParent(last);
- recycleBin.addScrapView(last);
+ recycleBin.addScrapView(last, mFirstPosition+lastIndex);
} else {
removeViewInLayout(last);
}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 1d612e2..7cf369f 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -65,12 +65,15 @@
private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
private TabImpl mSelectedTab;
+ private int mSavedTabPosition = INVALID_POSITION;
private ActionMode mActionMode;
private static final int CONTEXT_DISPLAY_NORMAL = 0;
private static final int CONTEXT_DISPLAY_SPLIT = 1;
+ private static final int INVALID_POSITION = -1;
+
private int mContextDisplayMode;
private boolean mClosingContext;
@@ -183,6 +186,8 @@
selectTab(null);
}
mTabs.clear();
+ mActionView.removeAllTabs();
+ mSavedTabPosition = INVALID_POSITION;
}
public void setTitle(CharSequence title) {
@@ -310,6 +315,8 @@
@Override
public void removeTabAt(int position) {
+ int selectedTabPosition = mSelectedTab != null
+ ? mSelectedTab.getPosition() : mSavedTabPosition;
mActionView.removeTabAt(position);
mTabs.remove(position);
@@ -318,7 +325,9 @@
mTabs.get(i).setPosition(i);
}
- selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1)));
+ if (selectedTabPosition == position) {
+ selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1)));
+ }
}
@Override
@@ -333,7 +342,13 @@
@Override
public void selectTab(Tab tab) {
- final FragmentTransaction trans = mActivity.getFragmentManager().openTransaction();
+ if (getNavigationMode() != NAVIGATION_MODE_TABS) {
+ mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION;
+ return;
+ }
+
+ final FragmentTransaction trans = mActivity.getFragmentManager().openTransaction()
+ .disallowAddToBackStack();
if (mSelectedTab == tab) {
if (mSelectedTab != null) {
@@ -623,12 +638,52 @@
}
@Override
+ public int getTabCount() {
+ return mTabs.size();
+ }
+
+ @Override
public void setNavigationMode(int mode) {
+ final int oldMode = mActionView.getNavigationMode();
+ switch (oldMode) {
+ case NAVIGATION_MODE_TABS:
+ mSavedTabPosition = getSelectedNavigationIndex();
+ selectTab(null);
+ break;
+ }
mActionView.setNavigationMode(mode);
+ switch (mode) {
+ case NAVIGATION_MODE_TABS:
+ if (mSavedTabPosition != INVALID_POSITION) {
+ setSelectedNavigationItem(mSavedTabPosition);
+ mSavedTabPosition = INVALID_POSITION;
+ }
+ break;
+ }
}
@Override
public Tab getTabAt(int index) {
return mTabs.get(index);
}
+
+ /**
+ * This fragment is added when we're keeping a back stack in a tab switch
+ * transaction. We use it to change the selected tab in the action bar view
+ * when we back out.
+ */
+ private class SwitchSelectedTabViewFragment extends Fragment {
+ private int mSelectedTabIndex;
+
+ public SwitchSelectedTabViewFragment(int oldSelectedTab) {
+ mSelectedTabIndex = oldSelectedTab;
+ }
+
+ @Override
+ public void onDetach() {
+ if (mSelectedTabIndex >= 0 && mSelectedTabIndex < getTabCount()) {
+ mActionView.setTabSelected(mSelectedTabIndex);
+ }
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 95d6dd3..8ead9c8 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -487,6 +487,12 @@
}
}
+ public void removeAllTabs() {
+ if (mTabLayout != null) {
+ mTabLayout.removeAllViews();
+ }
+ }
+
@Override
protected LayoutParams generateDefaultLayoutParams() {
// Used by custom nav views if they don't supply layout params. Everything else
diff --git a/core/java/com/android/internal/widget/WaveView.java b/core/java/com/android/internal/widget/WaveView.java
index f4ee7ee..f91d3d6 100644
--- a/core/java/com/android/internal/widget/WaveView.java
+++ b/core/java/com/android/internal/widget/WaveView.java
@@ -53,8 +53,10 @@
private static final int STATE_UNLOCK_SUCCESS = 5;
// Animation properties.
- private static final long DURATION = 500; // duration of transitional animations
- private static final long FINAL_DELAY = 1300; // delay for final animations
+ private static final long DURATION = 300; // duration of transitional animations
+ private static final long FINAL_DURATION = 200; // duration of final animations when unlocking
+ private static final long RING_DELAY = 1300; // when to start fading animated rings
+ private static final long FINAL_DELAY = 200; // delay for unlock success animation
private static final long SHORT_DELAY = 100; // for starting one animation after another.
private static final long WAVE_DURATION = 2000; // amount of time for way to expand/decay
private static final long RESET_TIMEOUT = 3000; // elapsed time of inactivity before we reset
@@ -299,11 +301,11 @@
// x:ringX, y:ringY, scaleX: .1, scaleY: .1, ease:Quint.easeOut});
DrawableHolder wave = mLightWaves.get(n);
long delay = 1000L*(6 + n - mCurrentWave)/10L;
- wave.addAnimTo(DURATION, delay, "x", ringX, true);
- wave.addAnimTo(DURATION, delay, "y", ringY, true);
- wave.addAnimTo(DURATION, delay, "scaleX", 0.1f, true);
- wave.addAnimTo(DURATION, delay, "scaleY", 0.1f, true);
- wave.addAnimTo(DURATION, delay, "alpha", 0.0f, true);
+ wave.addAnimTo(FINAL_DURATION, delay, "x", ringX, true);
+ wave.addAnimTo(FINAL_DURATION, delay, "y", ringY, true);
+ wave.addAnimTo(FINAL_DURATION, delay, "scaleX", 0.1f, true);
+ wave.addAnimTo(FINAL_DURATION, delay, "scaleY", 0.1f, true);
+ wave.addAnimTo(FINAL_DURATION, delay, "alpha", 0.0f, true);
}
for (int i = 0; i < mLightWaves.size(); i++) {
mLightWaves.get(i).startAnimations(this);
@@ -311,14 +313,14 @@
//TweenMax.to(unlockRing, .5, {x:ringX, y: ringY, scaleX: .1, scaleY: .1,
// alpha: 0, ease: Quint.easeOut });
- mUnlockRing.addAnimTo(DURATION, 0, "x", ringX, false);
- mUnlockRing.addAnimTo(DURATION, 0, "y", ringY, false);
- mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 0.1f, false);
- mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 0.1f, false);
- mUnlockRing.addAnimTo(DURATION, 0, "alpha", 0.0f, false);
+ mUnlockRing.addAnimTo(FINAL_DURATION, 0, "x", ringX, false);
+ mUnlockRing.addAnimTo(FINAL_DURATION, 0, "y", ringY, false);
+ mUnlockRing.addAnimTo(FINAL_DURATION, 0, "scaleX", 0.1f, false);
+ mUnlockRing.addAnimTo(FINAL_DURATION, 0, "scaleY", 0.1f, false);
+ mUnlockRing.addAnimTo(FINAL_DURATION, 0, "alpha", 0.0f, false);
//TweenMax.to(unlockRing, .5, { delay: 1.3, alpha: 0 , ease: Quint.easeOut });
- mUnlockRing.addAnimTo(DURATION, FINAL_DELAY, "alpha", 0.0f, false);
+ mUnlockRing.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
//TweenMax.to(unlockDefault, 0, { x:ringX, y: ringY, scaleX: .1, scaleY: .1,
// alpha: 0 , overwrite: true });
@@ -332,27 +334,27 @@
//TweenMax.to(unlockDefault, .5, { x:ringX, y: ringY, scaleX: 1, scaleY: 1,
// alpha: 1 , ease: Quint.easeOut , overwrite: true });
- mUnlockDefault.addAnimTo(DURATION, 0, "x", ringX, true);
- mUnlockDefault.addAnimTo(DURATION, 0, "y", ringY, true);
- mUnlockDefault.addAnimTo(DURATION, 0, "scaleX", 1.0f, true);
- mUnlockDefault.addAnimTo(DURATION, 0, "scaleY", 1.0f, true);
- mUnlockDefault.addAnimTo(DURATION, 0, "alpha", 1.0f, true);
+ mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "x", ringX, true);
+ mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "y", ringY, true);
+ mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "scaleX", 1.0f, true);
+ mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "scaleY", 1.0f, true);
+ mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "alpha", 1.0f, true);
//TweenMax.to(unlockDefault, .5, { delay: 1.3, scaleX: 3, scaleY: 3,
// alpha: 1, ease: Quint.easeOut });
- mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
- mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
- mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "alpha", 1.0f, false);
+ mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
+ mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
+ mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
//TweenMax.to(unlockHalo, .5, { x:ringX, y: ringY , ease: Back.easeOut });
- mUnlockHalo.addAnimTo(DURATION, 0, "x", ringX, false);
- mUnlockHalo.addAnimTo(DURATION, 0, "y", ringY, false);
+ mUnlockHalo.addAnimTo(FINAL_DURATION, 0, "x", ringX, false);
+ mUnlockHalo.addAnimTo(FINAL_DURATION, 0, "y", ringY, false);
//TweenMax.to(unlockHalo, .5, { delay: 1.3, scaleX: 3, scaleY: 3,
// alpha: 1, ease: Quint.easeOut });
- mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
- mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
- mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "alpha", 1.0f, false);
+ mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
+ mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
+ mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
removeCallbacks(mLockTimerActions);
@@ -437,7 +439,7 @@
//TweenMax.to(this["lightWave"+currentWave], 1, { delay: 1.3
// , alpha: 0 , ease:Quint.easeOut});
- wave.addAnimTo(1000, FINAL_DELAY, "alpha", 0.0f, false);
+ wave.addAnimTo(1000, RING_DELAY, "alpha", 0.0f, false);
wave.startAnimations(WaveView.this);
mCurrentWave = (mCurrentWave+1) % mWaveCount;
diff --git a/core/res/res/drawable/activated_background.xml b/core/res/res/drawable/activated_background.xml
index d92fba1..1047e5b 100644
--- a/core/res/res/drawable/activated_background.xml
+++ b/core/res/res/drawable/activated_background.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_activated="true" android:drawable="@android:drawable/list_selector_background_selected" />
<item android:drawable="@color/transparent" />
</selector>
diff --git a/core/res/res/drawable/activated_background_holo_dark.xml b/core/res/res/drawable/activated_background_holo_dark.xml
index febf2c4..a29bcb9 100644
--- a/core/res/res/drawable/activated_background_holo_dark.xml
+++ b/core/res/res/drawable/activated_background_holo_dark.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_activated="true" android:drawable="@android:drawable/list_activated_holo" />
<item android:drawable="@color/transparent" />
</selector>
diff --git a/core/res/res/drawable/activated_background_holo_light.xml b/core/res/res/drawable/activated_background_holo_light.xml
index febf2c4..a29bcb9 100644
--- a/core/res/res/drawable/activated_background_holo_light.xml
+++ b/core/res/res/drawable/activated_background_holo_light.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_activated="true" android:drawable="@android:drawable/list_activated_holo" />
<item android:drawable="@color/transparent" />
</selector>
diff --git a/core/res/res/drawable/activated_background_light.xml b/core/res/res/drawable/activated_background_light.xml
index 5d5681d..7d737db 100644
--- a/core/res/res/drawable/activated_background_light.xml
+++ b/core/res/res/drawable/activated_background_light.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_activated="true" android:drawable="@drawable/list_selector_background_selected_light" />
<item android:drawable="@color/transparent" />
</selector>
diff --git a/core/res/res/drawable/list_selector_background.xml b/core/res/res/drawable/list_selector_background.xml
index 6fb0661..f5eb12d 100644
--- a/core/res/res/drawable/list_selector_background.xml
+++ b/core/res/res/drawable/list_selector_background.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_window_focused="false" android:drawable="@color/transparent" />
diff --git a/core/res/res/drawable/list_selector_background_light.xml b/core/res/res/drawable/list_selector_background_light.xml
index 4da7e21..50a821b 100644
--- a/core/res/res/drawable/list_selector_background_light.xml
+++ b/core/res/res/drawable/list_selector_background_light.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_window_focused="false" android:drawable="@color/transparent" />
diff --git a/core/res/res/drawable/list_selector_holo_dark.xml b/core/res/res/drawable/list_selector_holo_dark.xml
index e4c5c52..9a6cb89 100644
--- a/core/res/res/drawable/list_selector_holo_dark.xml
+++ b/core/res/res/drawable/list_selector_holo_dark.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_window_focused="false" android:drawable="@color/transparent" />
diff --git a/core/res/res/drawable/list_selector_holo_light.xml b/core/res/res/drawable/list_selector_holo_light.xml
index 17631bd..844259e 100644
--- a/core/res/res/drawable/list_selector_holo_light.xml
+++ b/core/res/res/drawable/list_selector_holo_light.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item android:state_window_focused="false" android:drawable="@color/transparent" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a2fa1a3..1083452 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2786,6 +2786,10 @@
same pixel configuration as the screen (for instance: a ARGB 8888 bitmap with
an RGB 565 screen). -->
<attr name="dither" format="boolean" />
+ <!-- Amount of time (in milliseconds) to fade in a new state drawable. -->
+ <attr name="enterFadeDuration" format="integer" />
+ <!-- Amount of time (in milliseconds) to fade out an old state drawable. -->
+ <attr name="exitFadeDuration" format="integer" />
</declare-styleable>
<declare-styleable name="AnimationDrawable">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index fd7e984..f8752d3 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1358,6 +1358,8 @@
<public type="attr" name="buttonGroupStyle" />
<public type="attr" name="alertDialogButtonGroupStyle" />
<public type="attr" name="homeAsUpIndicator" />
+ <public type="attr" name="enterFadeDuration" />
+ <public type="attr" name="exitFadeDuration" />
<public type="anim" name="animator_fade_in" />
<public type="anim" name="animator_fade_out" />
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 7b2d9d7..baa9d62 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -423,6 +423,13 @@
}
/**
+ * If this Drawable does transition animations between states, ask that
+ * it immediately jump to the current state and skip any active animations.
+ */
+ public void jumpToCurrentState() {
+ }
+
+ /**
* @return The current drawable that will be used by this drawable. For simple drawables, this
* is just the drawable itself. For drawables that change state like
* {@link StateListDrawable} and {@link LevelListDrawable} this will be the child drawable
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 124d907..e55a746 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -21,6 +21,7 @@
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.os.SystemClock;
/**
* A helper class that contains several {@link Drawable}s and selects which one to use.
@@ -28,6 +29,8 @@
* You can subclass it to create your own DrawableContainers or directly use one its child classes.
*/
public class DrawableContainer extends Drawable implements Drawable.Callback {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "DrawableContainer";
/**
* To be proper, we should have a getter for dither (and alpha, etc.)
@@ -48,6 +51,12 @@
private int mCurIndex = -1;
private boolean mMutated;
+ // Animations.
+ private Runnable mAnimationRunnable;
+ private long mEnterAnimationEnd;
+ private long mExitAnimationEnd;
+ private Drawable mLastDrawable;
+
// overrides from Drawable
@Override
@@ -55,6 +64,9 @@
if (mCurrDrawable != null) {
mCurrDrawable.draw(canvas);
}
+ if (mLastDrawable != null) {
+ mLastDrawable.draw(canvas);
+ }
}
@Override
@@ -83,7 +95,11 @@
if (mAlpha != alpha) {
mAlpha = alpha;
if (mCurrDrawable != null) {
- mCurrDrawable.setAlpha(alpha);
+ if (mEnterAnimationEnd == 0) {
+ mCurrDrawable.setAlpha(alpha);
+ } else {
+ animate(false);
+ }
}
}
}
@@ -108,8 +124,29 @@
}
}
+ /**
+ * Change the global fade duration when a new drawable is entering
+ * the scene.
+ * @param ms The amount of time to fade in milliseconds.
+ */
+ public void setEnterFadeDuration(int ms) {
+ mDrawableContainerState.mEnterFadeDuration = ms;
+ }
+
+ /**
+ * Change the global fade duration when a new drawable is leaving
+ * the scene.
+ * @param ms The amount of time to fade in milliseconds.
+ */
+ public void setExitFadeDuration(int ms) {
+ mDrawableContainerState.mExitFadeDuration = ms;
+ }
+
@Override
protected void onBoundsChange(Rect bounds) {
+ if (mLastDrawable != null) {
+ mLastDrawable.setBounds(bounds);
+ }
if (mCurrDrawable != null) {
mCurrDrawable.setBounds(bounds);
}
@@ -121,7 +158,34 @@
}
@Override
+ public void jumpToCurrentState() {
+ boolean changed = false;
+ if (mLastDrawable != null) {
+ mLastDrawable.jumpToCurrentState();
+ mLastDrawable = null;
+ changed = true;
+ }
+ if (mCurrDrawable != null) {
+ mCurrDrawable.jumpToCurrentState();
+ }
+ if (mExitAnimationEnd != 0) {
+ mExitAnimationEnd = 0;
+ changed = true;
+ }
+ if (mEnterAnimationEnd != 0) {
+ mEnterAnimationEnd = 0;
+ changed = true;
+ }
+ if (changed) {
+ invalidateSelf();
+ }
+ }
+
+ @Override
protected boolean onStateChange(int[] state) {
+ if (mLastDrawable != null) {
+ return mLastDrawable.setState(state);
+ }
if (mCurrDrawable != null) {
return mCurrDrawable.setState(state);
}
@@ -130,6 +194,9 @@
@Override
protected boolean onLevelChange(int level) {
+ if (mLastDrawable != null) {
+ return mLastDrawable.setLevel(level);
+ }
if (mCurrDrawable != null) {
return mCurrDrawable.setLevel(level);
}
@@ -168,22 +235,19 @@
return mCurrDrawable != null ? mCurrDrawable.getMinimumHeight() : 0;
}
- public void invalidateDrawable(Drawable who)
- {
+ public void invalidateDrawable(Drawable who) {
if (who == mCurrDrawable && mCallback != null) {
mCallback.invalidateDrawable(this);
}
}
- public void scheduleDrawable(Drawable who, Runnable what, long when)
- {
+ public void scheduleDrawable(Drawable who, Runnable what, long when) {
if (who == mCurrDrawable && mCallback != null) {
mCallback.scheduleDrawable(this, what, when);
}
}
- public void unscheduleDrawable(Drawable who, Runnable what)
- {
+ public void unscheduleDrawable(Drawable who, Runnable what) {
if (who == mCurrDrawable && mCallback != null) {
mCallback.unscheduleDrawable(this, what);
}
@@ -192,6 +256,9 @@
@Override
public boolean setVisible(boolean visible, boolean restart) {
boolean changed = super.setVisible(visible, restart);
+ if (mLastDrawable != null) {
+ mLastDrawable.setVisible(visible, restart);
+ }
if (mCurrDrawable != null) {
mCurrDrawable.setVisible(visible, restart);
}
@@ -208,16 +275,39 @@
if (idx == mCurIndex) {
return false;
}
+
+ final long now = SystemClock.uptimeMillis();
+
+ if (DEBUG) android.util.Log.i(TAG, toString() + " from " + mCurIndex + " to " + idx
+ + ": exit=" + mDrawableContainerState.mExitFadeDuration
+ + " enter=" + mDrawableContainerState.mEnterFadeDuration);
+
+ if (mDrawableContainerState.mExitFadeDuration > 0) {
+ if (mLastDrawable != null) {
+ mLastDrawable.setVisible(false, false);
+ }
+ if (mCurrDrawable != null) {
+ mLastDrawable = mCurrDrawable;
+ mExitAnimationEnd = now + mDrawableContainerState.mExitFadeDuration;
+ } else {
+ mLastDrawable = null;
+ mExitAnimationEnd = 0;
+ }
+ } else if (mCurrDrawable != null) {
+ mCurrDrawable.setVisible(false, false);
+ }
+
if (idx >= 0 && idx < mDrawableContainerState.mNumChildren) {
Drawable d = mDrawableContainerState.mDrawables[idx];
- if (mCurrDrawable != null) {
- mCurrDrawable.setVisible(false, false);
- }
mCurrDrawable = d;
mCurIndex = idx;
if (d != null) {
+ if (mDrawableContainerState.mEnterFadeDuration > 0) {
+ mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration;
+ } else {
+ d.setAlpha(mAlpha);
+ }
d.setVisible(isVisible(), true);
- d.setAlpha(mAlpha);
d.setDither(mDrawableContainerState.mDither);
d.setColorFilter(mColorFilter);
d.setState(getState());
@@ -225,16 +315,72 @@
d.setBounds(getBounds());
}
} else {
- if (mCurrDrawable != null) {
- mCurrDrawable.setVisible(false, false);
- }
mCurrDrawable = null;
mCurIndex = -1;
}
+
+ if (mEnterAnimationEnd != 0 || mExitAnimationEnd != 0) {
+ if (mAnimationRunnable == null) {
+ mAnimationRunnable = new Runnable() {
+ @Override public void run() {
+ animate(true);
+ invalidateSelf();
+ }
+ };
+ } else {
+ unscheduleSelf(mAnimationRunnable);
+ }
+ // Compute first frame and schedule next animation.
+ animate(true);
+ }
+
invalidateSelf();
+
return true;
}
+ void animate(boolean schedule) {
+ final long now = SystemClock.uptimeMillis();
+ boolean animating = false;
+ if (mCurrDrawable != null) {
+ if (mEnterAnimationEnd != 0) {
+ if (mEnterAnimationEnd <= now) {
+ mCurrDrawable.setAlpha(mAlpha);
+ mEnterAnimationEnd = 0;
+ } else {
+ int animAlpha = (int)((mEnterAnimationEnd-now)*255)
+ / mDrawableContainerState.mEnterFadeDuration;
+ if (DEBUG) android.util.Log.i(TAG, toString() + " cur alpha " + animAlpha);
+ mCurrDrawable.setAlpha(((255-animAlpha)*mAlpha)/255);
+ animating = true;
+ }
+ }
+ } else {
+ mEnterAnimationEnd = 0;
+ }
+ if (mLastDrawable != null) {
+ if (mExitAnimationEnd != 0) {
+ if (mExitAnimationEnd <= now) {
+ mLastDrawable.setVisible(false, false);
+ mLastDrawable = null;
+ mExitAnimationEnd = 0;
+ } else {
+ int animAlpha = (int)((mExitAnimationEnd-now)*255)
+ / mDrawableContainerState.mExitFadeDuration;
+ if (DEBUG) android.util.Log.i(TAG, toString() + " last alpha " + animAlpha);
+ mLastDrawable.setAlpha((animAlpha*mAlpha)/255);
+ animating = true;
+ }
+ }
+ } else {
+ mExitAnimationEnd = 0;
+ }
+
+ if (schedule && animating) {
+ scheduleSelf(mAnimationRunnable, now + 1000/60);
+ }
+ }
+
@Override
public Drawable getCurrent() {
return mCurrDrawable;
@@ -300,6 +446,9 @@
boolean mDither = DEFAULT_DITHER;
+ int mEnterFadeDuration;
+ int mExitFadeDuration;
+
DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
Resources res) {
mOwner = owner;
@@ -340,6 +489,9 @@
mDither = orig.mDither;
+ mEnterFadeDuration = orig.mEnterFadeDuration;
+ mExitFadeDuration = orig.mExitFadeDuration;
+
} else {
mDrawables = new Drawable[10];
mNumChildren = 0;
@@ -476,6 +628,22 @@
}
}
+ public final void setEnterFadeDuration(int duration) {
+ mEnterFadeDuration = duration;
+ }
+
+ public final int getEnterFadeDuration() {
+ return mEnterFadeDuration;
+ }
+
+ public final void setExitFadeDuration(int duration) {
+ mExitFadeDuration = duration;
+ }
+
+ public final int getExitFadeDuration() {
+ return mExitFadeDuration;
+ }
+
public final int getOpacity() {
if (mHaveOpacity) {
return mOpacity;
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 239be40..384ca81 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -20,6 +20,7 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
+import java.util.Arrays;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -44,6 +45,7 @@
* @attr ref android.R.styleable#DrawableStates_state_checkable
* @attr ref android.R.styleable#DrawableStates_state_checked
* @attr ref android.R.styleable#DrawableStates_state_selected
+ * @attr ref android.R.styleable#DrawableStates_state_activated
* @attr ref android.R.styleable#DrawableStates_state_active
* @attr ref android.R.styleable#DrawableStates_state_single
* @attr ref android.R.styleable#DrawableStates_state_first
@@ -52,6 +54,9 @@
* @attr ref android.R.styleable#DrawableStates_state_pressed
*/
public class StateListDrawable extends DrawableContainer {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "StateListDrawable";
+
/**
* To be proper, we should have a getter for dither (and alpha, etc.)
* so that proxy classes like this can save/restore their delegates'
@@ -93,6 +98,8 @@
@Override
protected boolean onStateChange(int[] stateSet) {
int idx = mStateListState.indexOfStateSet(stateSet);
+ if (DEBUG) android.util.Log.i(TAG, "onStateChange " + this + " states "
+ + Arrays.toString(stateSet) + " found " + idx);
if (idx < 0) {
idx = mStateListState.indexOfStateSet(StateSet.WILD_CARD);
}
@@ -117,6 +124,10 @@
com.android.internal.R.styleable.StateListDrawable_variablePadding, false));
mStateListState.setConstantSize(a.getBoolean(
com.android.internal.R.styleable.StateListDrawable_constantSize, false));
+ mStateListState.setEnterFadeDuration(a.getInt(
+ com.android.internal.R.styleable.StateListDrawable_enterFadeDuration, 0));
+ mStateListState.setExitFadeDuration(a.getInt(
+ com.android.internal.R.styleable.StateListDrawable_exitFadeDuration, 0));
setDither(a.getBoolean(com.android.internal.R.styleable.StateListDrawable_dither,
DEFAULT_DITHER));
@@ -251,7 +262,7 @@
}
static final class StateListState extends DrawableContainerState {
- private int[][] mStateSets;
+ int[][] mStateSets;
StateListState(StateListState orig, StateListDrawable owner, Resources res) {
super(orig, owner, res);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 855a4e0..09e01f6 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -260,25 +260,25 @@
const GLuint previousFbo = mSnapshot->fbo;
const int count = saveSnapshot(flags);
- int alpha = 255;
- SkXfermode::Mode mode;
+ if (!mSnapshot->invisible) {
+ int alpha = 255;
+ SkXfermode::Mode mode;
- if (p) {
- alpha = p->getAlpha();
- if (!mCaches.extensions.hasFramebufferFetch()) {
- const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
- if (!isMode) {
- // Assume SRC_OVER
- mode = SkXfermode::kSrcOver_Mode;
+ if (p) {
+ alpha = p->getAlpha();
+ if (!mCaches.extensions.hasFramebufferFetch()) {
+ const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
+ if (!isMode) {
+ // Assume SRC_OVER
+ mode = SkXfermode::kSrcOver_Mode;
+ }
+ } else {
+ mode = getXfermode(p->getXfermode());
}
} else {
- mode = getXfermode(p->getXfermode());
+ mode = SkXfermode::kSrcOver_Mode;
}
- } else {
- mode = SkXfermode::kSrcOver_Mode;
- }
- if (!mSnapshot->previous->invisible) {
createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags, previousFbo);
}
@@ -379,8 +379,7 @@
bounds.getHeight() > mCaches.maxTextureSize) {
snapshot->invisible = true;
} else {
- snapshot->invisible = snapshot->previous->invisible ||
- (alpha <= ALPHA_THRESHOLD && fboLayer);
+ snapshot->invisible = snapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
}
// Bail out if we won't draw in this snapshot
@@ -1011,6 +1010,9 @@
}
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
+ // No need to check against the clip, we fill the clip region
+ if (mSnapshot->invisible) return;
+
Rect& clip(*mSnapshot->clipRect);
clip.snapToPixelBoundaries();
drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 4644a7c..50d10bf 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -219,7 +219,7 @@
}
class WaveViewMethods implements WaveView.OnTriggerListener {
- private static final int WAIT_FOR_ANIMATION_TIMEOUT = 500;
+ private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
/** {@inheritDoc} */
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 185d413..c3ad9e6 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -261,8 +261,10 @@
protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
//***** Member Variables
+ protected int mId;
protected int mTag;
protected PhoneBase phone;
+ protected RetryManager mRetryMgr;
protected int cid;
protected LinkProperties mLinkProperties = new LinkProperties();
protected LinkCapabilities mCapabilities = new LinkCapabilities();
@@ -285,10 +287,11 @@
//***** Constructor
- protected DataConnection(PhoneBase phone, String name) {
+ protected DataConnection(PhoneBase phone, String name, RetryManager rm) {
super(name);
if (DBG) log("DataConnection constructor E");
this.phone = phone;
+ mRetryMgr = rm;
this.cid = -1;
clearSettings();
@@ -358,8 +361,8 @@
if (dp.onCompletedMsg != null) {
Message msg = dp.onCompletedMsg;
- log(String.format("msg.what=%d msg.obj=%s",
- msg.what, ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
+ log(String.format("msg=%s msg.obj=%s", msg.toString(),
+ ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
AsyncResult.forMessage(msg);
msg.sendToTarget();
}
@@ -372,6 +375,10 @@
clearSettings();
}
+ public RetryManager getRetryMgr() {
+ return mRetryMgr;
+ }
+
/**
* Clear all settings called when entering mInactiveState.
*/
@@ -857,13 +864,13 @@
/**
* Connect to the apn and return an AsyncResult in onCompletedMsg.
- * Used for cellular networks that use Acess Point Names (APN) such
+ * Used for cellular networks that use Acesss Point Names (APN) such
* as GSM networks.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj,
* AsyncResult.result = FailCause and AsyncResult.exception = Exception().
- * @param apn is the Acces Point Name to connect to
+ * @param apn is the Access Point Name to connect to
*/
public void connect(Message onCompletedMsg, ApnSetting apn) {
sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg)));
@@ -915,6 +922,13 @@
}
/**
+ * Get the DataConnection ID
+ */
+ public int getDataConnectionId() {
+ return mId;
+ }
+
+ /**
* Return the LinkProperties for the connection.
*
* @return a copy of the LinkProperties, is never null.
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 52839be..f8812ec 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -16,27 +16,38 @@
package com.android.internal.telephony;
+import com.android.internal.telephony.cdma.CDMAPhone;
+
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.net.IConnectivityManager;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
+import android.os.ServiceManager;
+import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
-
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* {@hide}
- *
*/
public abstract class DataConnectionTracker extends Handler {
- protected static final boolean DBG = false;
- protected final String LOG_TAG = "DataConnectionTracker";
+ protected static final boolean DBG = true;
/**
* IDLE: ready to start data connection setup, default state
@@ -121,9 +132,10 @@
protected boolean mMasterDataEnabled = true;
protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
+
protected int enabledCount = 0;
- /* Currently requested APN type */
+ /* Currently requested APN type (TODO: This should probably be a parameter not a member) */
protected String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
/** Retry configuration: A doubling of retry times from 5secs to 30minutes */
@@ -165,20 +177,27 @@
// represents an invalid IP address
protected static final String NULL_IP = "0.0.0.0";
+ // TODO: See if we can remove INTENT_RECONNECT_ALARM
+ // having to have different values for GSM and
+ // CDMA. If so we can then remove the need for
+ // getActionIntentReconnectAlarm.
+ protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
// member variables
- protected PhoneBase phone;
- protected Activity activity = Activity.NONE;
- protected State state = State.IDLE;
+ protected PhoneBase mPhone;
+ protected Activity mActivity = Activity.NONE;
+ protected State mState = State.IDLE;
protected Handler mDataConnectionTracker = null;
- protected long txPkts, rxPkts, sentSinceLastRecv;
- protected int netStatPollPeriod;
+ protected long mTxPkts;
+ protected long mRxPkts;
+ protected long mSentSinceLastRecv;
+ protected int mNetStatPollPeriod;
protected int mNoRecvPollCount = 0;
- protected boolean netStatPollEnabled = false;
+ protected boolean mNetStatPollEnabled = false;
- /** Manage the behavior of data retry after failure */
+ /** Manage the behavior of data retry after failure (TODO: One per connection in the future?) */
protected RetryManager mRetryMgr = new RetryManager();
// wifi connection status will be updated by sticky intent
@@ -188,37 +207,125 @@
protected PendingIntent mReconnectIntent = null;
/** CID of active data connection */
- protected int cidActive;
+ protected int mCidActive;
/** indication of our availability (preconditions to trysetupData are met) **/
protected boolean mAvailability = false;
+ // When false we will not auto attach and manully attaching is required.
+ protected boolean mAutoAttachOnCreation = false;
+
+ // State of screen
+ // (TODO: Reconsider tying directly to screen, maybe this is
+ // really a lower power mode")
+ protected boolean mIsScreenOn = true;
+
/** The link properties (dns, gateway, ip, etc) */
protected LinkProperties mLinkProperties = new LinkProperties();
/** The link capabilities */
protected LinkCapabilities mLinkCapabilities = new LinkCapabilities();
+ /** Allows the generation of unique Id's for DataConnection objects */
+ protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
+
+ /** The data connections. */
+ protected HashMap<Integer, DataConnection> mDataConnections =
+ new HashMap<Integer, DataConnection>();
+
+ protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
+ {
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ mIsScreenOn = true;
+ stopNetStatPoll();
+ startNetStatPoll();
+ } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ mIsScreenOn = false;
+ stopNetStatPoll();
+ startNetStatPoll();
+ } else if (action.equals(getActionIntentReconnectAlarm())) {
+ log("Reconnect alarm. Previous state was " + mState);
+
+ String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+ if (mState == State.FAILED) {
+ Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 0; // tearDown is false
+ msg.obj = reason;
+ sendMessage(msg);
+ }
+ sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+ } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ final android.net.NetworkInfo networkInfo = (NetworkInfo)
+ intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
+ } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
+
+ if (!enabled) {
+ // when WiFi got disabled, the NETWORK_STATE_CHANGED_ACTION
+ // quit and won't report disconnected until next enabling.
+ mIsWifiConnected = false;
+ }
+ }
+ }
+ };
+
/**
* Default constructor
*/
protected DataConnectionTracker(PhoneBase phone) {
super();
- this.phone = phone;
+ mPhone = phone;
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(getActionIntentReconnectAlarm());
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+
+ // TODO: Why is this registering the phone as the receiver of the intent
+ // and not its own handler?
+ mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+
+ // This preference tells us 1) initial condition for "dataEnabled",
+ // and 2) whether the RIL will setup the baseband to auto-PS attach.
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
+ boolean dataEnabledSetting = true;
+ try {
+ dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
+ getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
+ } catch (Exception e) {
+ // nothing to do - use the old behavior and leave data on
+ }
+ dataEnabled[APN_DEFAULT_ID] =
+ !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false) &&
+ dataEnabledSetting;
+ if (dataEnabled[APN_DEFAULT_ID]) {
+ enabledCount++;
+ }
+ mAutoAttachOnCreation = dataEnabled[APN_DEFAULT_ID];
}
- public abstract void dispose();
+ public void dispose() {
+ mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
+ }
public Activity getActivity() {
- return activity;
+ return mActivity;
}
public State getState() {
- return state;
+ return mState;
}
public String getStateInString() {
- switch (state) {
+ switch (mState) {
case IDLE: return "IDLE";
case INITING: return "INIT";
case CONNECTING: return "CING";
@@ -231,6 +338,14 @@
}
/**
+ * @return the data connections
+ */
+ public ArrayList<DataConnection> getAllDataConnections() {
+ /** TODO: change return type to Collection? */
+ return new ArrayList<DataConnection>(mDataConnections.values());
+ }
+
+ /**
* The data connection is expected to be setup while device
* 1. has Icc card
* 2. registered for data service
@@ -246,9 +361,9 @@
// the shared values. If it is not, then update it.
public void setDataOnRoamingEnabled(boolean enabled) {
if (getDataOnRoamingEnabled() != enabled) {
- Settings.Secure.putInt(phone.getContext().getContentResolver(),
+ Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
- if (phone.getServiceState().getRoaming()) {
+ if (mPhone.getServiceState().getRoaming()) {
if (enabled) {
mRetryMgr.resetRetryCount();
}
@@ -257,16 +372,19 @@
}
}
- //Retrieve the data roaming setting from the shared preferences.
+ // Retrieve the data roaming setting from the shared preferences.
public boolean getDataOnRoamingEnabled() {
try {
- return Settings.Secure.getInt(phone.getContext().getContentResolver(),
- Settings.Secure.DATA_ROAMING) > 0;
+ return Settings.Secure.getInt(
+ mPhone.getContext().getContentResolver(), Settings.Secure.DATA_ROAMING) > 0;
} catch (SettingNotFoundException snfe) {
return false;
}
}
+
+ protected abstract String getActionIntentReconnectAlarm();
+
// abstract handler methods
protected abstract boolean onTrySetupData(String reason);
protected abstract void onRoamingOff();
@@ -274,14 +392,14 @@
protected abstract void onRadioAvailable();
protected abstract void onRadioOffOrNotAvailable();
protected abstract void onDataSetupComplete(AsyncResult ar);
- protected abstract void onDisconnectDone(AsyncResult ar);
+ protected abstract void onDisconnectDone(int connId, AsyncResult ar);
protected abstract void onResetDone(AsyncResult ar);
protected abstract void onVoiceCallStarted();
protected abstract void onVoiceCallEnded();
protected abstract void onCleanUpConnection(boolean tearDown, String reason);
@Override
- public void handleMessage (Message msg) {
+ public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_ENABLE_NEW_APN:
@@ -291,7 +409,7 @@
case EVENT_TRY_SETUP_DATA:
String reason = null;
if (msg.obj instanceof String) {
- reason = (String)msg.obj;
+ reason = (String) msg.obj;
}
onTrySetupData(reason);
break;
@@ -316,12 +434,13 @@
break;
case EVENT_DATA_SETUP_COMPLETE:
- cidActive = msg.arg1;
+ mCidActive = msg.arg1;
onDataSetupComplete((AsyncResult) msg.obj);
break;
case EVENT_DISCONNECT_DONE:
- onDisconnectDone((AsyncResult) msg.obj);
+ log("DataConnectoinTracker.handleMessage: EVENT_DISCONNECT_DONE msg=" + msg);
+ onDisconnectDone(msg.arg1, (AsyncResult) msg.obj);
break;
case EVENT_VOICE_CALL_STARTED:
@@ -334,7 +453,7 @@
case EVENT_CLEAN_UP_CONNECTION:
boolean tearDown = (msg.arg1 == 0) ? false : true;
- onCleanUpConnection(tearDown, (String)msg.obj);
+ onCleanUpConnection(tearDown, (String) msg.obj);
break;
case EVENT_SET_MASTER_DATA_ENABLE:
@@ -354,8 +473,9 @@
/**
* Report the current state of data connectivity (enabled or disabled)
+ *
* @return {@code false} if data connectivity has been explicitly disabled,
- * {@code true} otherwise.
+ * {@code true} otherwise.
*/
public synchronized boolean getDataEnabled() {
return dataEnabled[APN_DEFAULT_ID];
@@ -363,8 +483,9 @@
/**
* Report on whether data connectivity is enabled
+ *
* @return {@code false} if data connectivity has been explicitly disabled,
- * {@code true} otherwise.
+ * {@code true} otherwise.
*/
public boolean getAnyDataEnabled() {
return (enabledCount != 0);
@@ -378,6 +499,8 @@
protected abstract void log(String s);
+ protected abstract void loge(String s);
+
protected int apnTypeToId(String type) {
if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
return APN_DEFAULT_ID;
@@ -407,7 +530,7 @@
case APN_HIPRI_ID:
return Phone.APN_TYPE_HIPRI;
default:
- Log.e(LOG_TAG, "Unknown id (" + id + ") in apnIdToType");
+ log("Unknown id (" + id + ") in apnIdToType");
return Phone.APN_TYPE_DEFAULT;
}
}
@@ -420,8 +543,6 @@
protected abstract String getActiveApnString();
- public abstract ArrayList<DataConnection> getAllDataConnections();
-
protected abstract void setState(State s);
protected LinkProperties getLinkProperties(String apnType) {
@@ -467,33 +588,34 @@
protected void notifyDataConnection(String reason) {
for (int id = 0; id < APN_NUM_TYPES; id++) {
if (dataEnabled[id]) {
- phone.notifyDataConnection(reason, apnIdToType(id));
+ mPhone.notifyDataConnection(reason, apnIdToType(id));
}
}
notifyDataAvailability(reason);
}
- // a new APN has gone active and needs to send events to catch up with the current condition
+ // a new APN has gone active and needs to send events to catch up with the
+ // current condition
private void notifyApnIdUpToCurrent(String reason, int apnId) {
- switch (state) {
+ switch (mState) {
case IDLE:
case INITING:
break;
case CONNECTING:
case SCANNING:
- phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
+ mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
break;
case CONNECTED:
case DISCONNECTING:
- phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
- phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTED);
+ mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
+ mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTED);
break;
}
}
// since we normally don't send info to a disconnected APN, we need to do this specially
private void notifyApnIdDisconnected(String reason, int apnId) {
- phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.DISCONNECTED);
+ mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.DISCONNECTED);
}
// disabled apn's still need avail/unavail notificiations - send them out
@@ -526,10 +648,10 @@
* @return {@code true} if data connectivity is possible, {@code false} otherwise.
*/
protected boolean isDataPossible() {
- boolean possible = (isDataAllowed() &&
- !(getDataEnabled() && (state == State.FAILED || state == State.IDLE)));
+ boolean possible = (isDataAllowed()
+ && !(getDataEnabled() && (mState == State.FAILED || mState == State.IDLE)));
if (!possible && DBG && isDataAllowed()) {
- log("Data not possible. No coverage: dataState = " + state);
+ log("Data not possible. No coverage: dataState = " + mState);
}
return possible;
}
@@ -549,13 +671,13 @@
/**
* Ensure that we are connected to an APN of the specified type.
- * @param type the APN type (currently the only valid values
- * are {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
- * @return the result of the operation. Success is indicated by
- * a return value of either {@code Phone.APN_ALREADY_ACTIVE} or
- * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a broadcast
- * will be sent by the ConnectivityManager when a connection to
- * the APN has been established.
+ *
+ * @param type the APN type (currently the only valid values are
+ * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
+ * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
+ * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
+ * broadcast will be sent by the ConnectivityManager when a
+ * connection to the APN has been established.
*/
public synchronized int enableApnType(String type) {
int id = apnTypeToId(type);
@@ -564,13 +686,12 @@
}
if (DBG) {
- Log.d(LOG_TAG, "enableApnType(" + type + "), isApnTypeActive = "
- + isApnTypeActive(type) + ", isApnIdEnabled =" + isApnIdEnabled(id) +
- " and state = " + state);
+ log("enableApnType(" + type + "), isApnTypeActive = " + isApnTypeActive(type)
+ + ", isApnIdEnabled =" + isApnIdEnabled(id) + " and state = " + mState);
}
if (!isApnTypeAvailable(type)) {
- if (DBG) Log.d(LOG_TAG, "type not available");
+ if (DBG) log("type not available");
return Phone.APN_TYPE_NOT_AVAILABLE;
}
@@ -583,15 +704,21 @@
}
/**
- * The APN of the specified type is no longer needed. Ensure that if
- * use of the default APN has not been explicitly disabled, we are connected
- * to the default APN.
+ * The APN of the specified type is no longer needed. Ensure that if use of
+ * the default APN has not been explicitly disabled, we are connected to the
+ * default APN.
+ *
* @param type the APN type. The only valid values are currently
- * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
- * @return
+ * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
+ * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
+ * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
+ * broadcast will be sent by the ConnectivityManager when a
+ * connection to the APN has been disconnected. A {@code
+ * Phone.APN_REQUEST_FAILED} is returned if the type parameter is
+ * invalid or if the apn wasn't enabled.
*/
public synchronized int disableApnType(String type) {
- if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
+ if (DBG) log("disableApnType(" + type + ")");
int id = apnTypeToId(type);
if (id == APN_INVALID_ID) {
return Phone.APN_REQUEST_FAILED;
@@ -614,8 +741,8 @@
private void setEnabled(int id, boolean enable) {
if (DBG) {
- Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = "
- + dataEnabled[id] + " and enabledCount = " + enabledCount);
+ log("setEnabled(" + id + ", " + enable + ") with old state = " + dataEnabled[id]
+ + " and enabledCount = " + enabledCount);
}
Message msg = obtainMessage(EVENT_ENABLE_NEW_APN);
msg.arg1 = id;
@@ -625,9 +752,10 @@
protected synchronized void onEnableApn(int apnId, int enabled) {
if (DBG) {
- Log.d(LOG_TAG, "EVENT_APN_ENABLE_REQUEST " + apnId + ", " + enabled);
- Log.d(LOG_TAG, " dataEnabled = " + dataEnabled[apnId] + ", enabledCount = "
- + enabledCount + ", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId)));
+ log("EVENT_APN_ENABLE_REQUEST apnId=" + apnId + ", apnType=" + apnIdToType(apnId) +
+ ", enabled=" + enabled + ", dataEnabled = " + dataEnabled[apnId] +
+ ", enabledCount = " + enabledCount + ", isApnTypeActive = " +
+ isApnTypeActive(apnIdToType(apnId)));
}
if (enabled == ENABLED) {
if (!dataEnabled[apnId]) {
@@ -676,18 +804,22 @@
}
/**
- * Prevent mobile data connections from being established,
- * or once again allow mobile data connections. If the state
- * toggles, then either tear down or set up data, as
- * appropriate to match the new state.
- * <p>This operation only affects the default APN, and if the same APN is
- * currently being used for MMS traffic, the teardown will not happen
- * even when {@code enable} is {@code false}.</p>
- * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
+ * Prevent mobile data connections from being established, or once again
+ * allow mobile data connections. If the state toggles, then either tear
+ * down or set up data, as appropriate to match the new state.
+ * <p>
+ * This operation only affects the default APN, and if the same APN is
+ * currently being used for MMS traffic, the teardown will not happen even
+ * when {@code enable} is {@code false}.
+ * </p>
+ *
+ * @param enable indicates whether to enable ({@code true}) or disable (
+ * {@code false}) data
* @return {@code true} if the operation succeeded
*/
public boolean setDataEnabled(boolean enable) {
- if (DBG) Log.d(LOG_TAG, "setDataEnabled(" + enable + ")");
+ if (DBG)
+ log("setDataEnabled(" + enable + ")");
Message msg = obtainMessage(EVENT_SET_MASTER_DATA_ENABLE);
msg.arg1 = (enable ? ENABLED : DISABLED);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index 95cb1c6..8072c44 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -23,6 +23,7 @@
import com.android.internal.telephony.gsm.ApnSetting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.RetryManager;
/**
* {@hide}
@@ -39,23 +40,27 @@
// ***** Constructor
- private CdmaDataConnection(CDMAPhone phone, String name) {
- super(phone, name);
+ private CdmaDataConnection(CDMAPhone phone, String name, RetryManager rm) {
+ super(phone, name, rm);
}
/**
* Create the connection object
*
- * @param phone
+ * @param phone the Phone
+ * @param id the connection id
+ * @param rm the RetryManager
* @return CdmaDataConnection that was created.
*/
- static CdmaDataConnection makeDataConnection(CDMAPhone phone) {
+ static CdmaDataConnection makeDataConnection(CDMAPhone phone, int id, RetryManager rm) {
synchronized (mCountLock) {
mCount += 1;
}
- CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, "CdmaDataConnection-" + mCount);
+ CdmaDataConnection cdmaDc = new CdmaDataConnection(phone,
+ "CdmaDataConnection-" + mCount, rm);
cdmaDc.start();
if (DBG) cdmaDc.log("Made " + cdmaDc.getName());
+ cdmaDc.mId = id;
return cdmaDc;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index e499e95..7c652c5 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -18,21 +18,13 @@
import android.app.AlarmManager;
import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.net.IConnectivityManager;
-import android.net.NetworkInfo;
import android.net.TrafficStats;
-import android.net.wifi.WifiManager;
import android.os.AsyncResult;
import android.os.Message;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.preference.PreferenceManager;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
@@ -46,6 +38,7 @@
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.gsm.ApnSetting;
import com.android.internal.telephony.Phone;
@@ -59,20 +52,11 @@
private CDMAPhone mCdmaPhone;
- // Indicates baseband will not auto-attach
- private boolean noAutoAttach = false;
- private boolean mIsScreenOn = true;
-
//useful for debugging
- boolean failNextConnect = false;
+ boolean mFailNextConnect = false;
- /**
- * dataConnectionList holds all the Data connection
- */
- private ArrayList<DataConnection> dataConnectionList;
-
- /** Currently active CdmaDataConnection */
- private CdmaDataConnection mActiveDataConnection;
+ /** The DataConnection being setup */
+ private CdmaDataConnection mPendingDataConnection;
private boolean mPendingRestartRadio = false;
private static final int TIME_DELAYED_TO_RESTART_RADIO =
@@ -83,10 +67,8 @@
*/
private static final int DATA_CONNECTION_POOL_SIZE = 1;
- private static final int POLL_CONNECTION_MILLIS = 5 * 1000;
private static final String INTENT_RECONNECT_ALARM =
- "com.android.internal.telephony.cdma-reconnect";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
+ "com.android.internal.telephony.cdma-reconnect";
/**
* Constants for the data connection activity:
@@ -110,49 +92,6 @@
// if we have no active Apn this is null
protected ApnSetting mActiveApn;
- // Possibly promote to base class, the only difference is
- // the INTENT_RECONNECT_ALARM action is a different string.
- // Do consider technology changes if it is promoted.
- BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
- {
- @Override
- public void onReceive(Context context, Intent intent)
- {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_SCREEN_ON)) {
- mIsScreenOn = true;
- stopNetStatPoll();
- startNetStatPoll();
- } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- mIsScreenOn = false;
- stopNetStatPoll();
- startNetStatPoll();
- } else if (action.equals((INTENT_RECONNECT_ALARM))) {
- Log.d(LOG_TAG, "Data reconnect alarm. Previous state was " + state);
-
- String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
- if (state == State.FAILED) {
- cleanUpConnection(false, reason);
- }
- trySetupData(reason);
- } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- final android.net.NetworkInfo networkInfo = (NetworkInfo)
- intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
- } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
- if (!enabled) {
- // when wifi got disabeled, the NETWORK_STATE_CHANGED_ACTION
- // quit and wont report disconnected til next enalbing.
- mIsWifiConnected = false;
- }
- }
- }
- };
-
-
/* Constructor */
CdmaDataConnectionTracker(CDMAPhone p) {
@@ -172,79 +111,49 @@
p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null);
- IntentFilter filter = new IntentFilter();
- filter.addAction(INTENT_RECONNECT_ALARM);
- filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-
- // TODO: Why is this registering the phone as the receiver of the intent
- // and not its own handler?
- p.getContext().registerReceiver(mIntentReceiver, filter, null, p);
-
mDataConnectionTracker = this;
createAllDataConnectionList();
-
- // This preference tells us 1) initial condition for "dataEnabled",
- // and 2) whether the RIL will setup the baseband to auto-PS attach.
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
-
- boolean dataEnabledSetting = true;
- try {
- dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
- getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
- } catch (Exception e) {
- // nothing to do - use the old behavior and leave data on
- }
- dataEnabled[APN_DEFAULT_ID] =
- !sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false) &&
- dataEnabledSetting;
- if (dataEnabled[APN_DEFAULT_ID]) {
- enabledCount++;
- }
- noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
-
- if (!mRetryMgr.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
- if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) {
- // Should never happen, log an error and default to a simple linear sequence.
- Log.e(LOG_TAG, "Could not configure using DEFAULT_DATA_RETRY_CONFIG="
- + DEFAULT_DATA_RETRY_CONFIG);
- mRetryMgr.configure(20, 2000, 1000);
- }
- }
}
+ @Override
public void dispose() {
+ super.dispose();
+
// Unregister from all events
- phone.mCM.unregisterForAvailable(this);
- phone.mCM.unregisterForOffOrNotAvailable(this);
+ mPhone.mCM.unregisterForAvailable(this);
+ mPhone.mCM.unregisterForOffOrNotAvailable(this);
mCdmaPhone.mRuimRecords.unregisterForRecordsLoaded(this);
- phone.mCM.unregisterForNVReady(this);
- phone.mCM.unregisterForDataStateChanged(this);
+ mPhone.mCM.unregisterForNVReady(this);
+ mPhone.mCM.unregisterForDataStateChanged(this);
mCdmaPhone.mCT.unregisterForVoiceCallEnded(this);
mCdmaPhone.mCT.unregisterForVoiceCallStarted(this);
mCdmaPhone.mSST.unregisterForCdmaDataConnectionAttached(this);
mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this);
mCdmaPhone.mSST.unregisterForRoamingOn(this);
mCdmaPhone.mSST.unregisterForRoamingOff(this);
- phone.mCM.unregisterForCdmaOtaProvision(this);
+ mPhone.mCM.unregisterForCdmaOtaProvision(this);
- phone.getContext().unregisterReceiver(this.mIntentReceiver);
destroyAllDataConnectionList();
}
+ @Override
protected void finalize() {
- if(DBG) Log.d(LOG_TAG, "CdmaDataConnectionTracker finalized");
+ if(DBG) log("CdmaDataConnectionTracker finalized");
}
+ @Override
+ protected String getActionIntentReconnectAlarm() {
+ return INTENT_RECONNECT_ALARM;
+ }
+
+ @Override
protected void setState(State s) {
if (DBG) log ("setState: " + s);
- if (state != s) {
+ if (mState != s) {
EventLog.writeEvent(EventLogTags.CDMA_DATA_STATE_CHANGE,
- state.toString(), s.toString());
- state = s;
+ mState.toString(), s.toString());
+ mState = s;
}
}
@@ -263,6 +172,7 @@
return false;
}
+ @Override
protected String[] getActiveApnTypes() {
String[] result;
if (mActiveApn != null) {
@@ -274,6 +184,7 @@
return result;
}
+ @Override
protected String getActiveApnString() {
return null;
}
@@ -287,45 +198,51 @@
*
* @return false while no data connection if all above requirements are met.
*/
+ @Override
public boolean isDataConnectionAsDesired() {
- boolean roaming = phone.getServiceState().getRoaming();
+ boolean roaming = mPhone.getServiceState().getRoaming();
- if (((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
+ if (((mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
(mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
ServiceState.STATE_IN_SERVICE) &&
(!roaming || getDataOnRoamingEnabled()) &&
!mIsWifiConnected ) {
- return (state == State.CONNECTED);
+ return (mState == State.CONNECTED);
}
return true;
}
+ @Override
protected boolean isDataAllowed() {
int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
- boolean roaming = (phone.getServiceState().getRoaming() && !getDataOnRoamingEnabled());
+ boolean roaming = (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled());
boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
- boolean allowed = (psState == ServiceState.STATE_IN_SERVICE &&
- (phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
- mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
- (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
- phone.getState() == Phone.State.IDLE) &&
- !roaming &&
- mMasterDataEnabled &&
- desiredPowerState &&
- !mPendingRestartRadio &&
- !mCdmaPhone.needsOtaServiceProvisioning());
+ boolean allowed =
+ (psState == ServiceState.STATE_IN_SERVICE ||
+ mAutoAttachOnCreation) &&
+ (mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
+ mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
+ (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+ mPhone.getState() == Phone.State.IDLE) &&
+ !roaming &&
+ mMasterDataEnabled &&
+ desiredPowerState &&
+ !mPendingRestartRadio &&
+ !mCdmaPhone.needsOtaServiceProvisioning();
if (!allowed && DBG) {
String reason = "";
- if (psState != ServiceState.STATE_IN_SERVICE) reason += " - psState= " + psState;
- if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY &&
- !mCdmaPhone.mRuimRecords.getRecordsLoaded()) {
- reason += " - radioState= " + phone.mCM.getRadioState() + " - RUIM not loaded";
+ if (!((psState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
+ reason += " - psState= " + psState;
}
- if (phone.getState() != Phone.State.IDLE &&
+ if (!(mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
+ mCdmaPhone.mRuimRecords.getRecordsLoaded())) {
+ reason += " - radioState= " + mPhone.mCM.getRadioState() + " - RUIM not loaded";
+ }
+ if (mPhone.getState() != Phone.State.IDLE &&
mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
- reason += " - concurrentVoiceAndData not allowed and state= " + phone.getState();
+ reason += " - concurrentVoiceAndData not allowed and state= " + mPhone.getState();
}
if (roaming) reason += " - Roaming";
if (!mMasterDataEnabled) reason += " - mMasterDataEnabled= false";
@@ -340,22 +257,22 @@
private boolean trySetupData(String reason) {
if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
- if (phone.getSimulatedRadioControl() != null) {
+ if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
setState(State.CONNECTED);
notifyDataConnection(reason);
notifyOffApnsOfAvailability(reason, true);
- Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected");
+ log("(fix?) We're on the simulator; assuming data is connected");
return true;
}
int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
- boolean roaming = phone.getServiceState().getRoaming();
+ boolean roaming = mPhone.getServiceState().getRoaming();
boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
- if ((state == State.IDLE || state == State.SCANNING) &&
+ if ((mState == State.IDLE || mState == State.SCANNING) &&
isDataAllowed() && getAnyDataEnabled()) {
boolean retValue = setupData(reason);
notifyOffApnsOfAvailability(reason, retValue);
@@ -367,13 +284,12 @@
}
/**
- * If tearDown is true, this only tears down a CONNECTED session. Presently,
- * there is no mechanism for abandoning an INITING/CONNECTING session,
- * but would likely involve cancelling pending async requests or
- * setting a flag or new state to ignore them when they came in
- * @param tearDown true if the underlying DataConnection should be
- * disconnected.
- * @param reason reason for the clean up.
+ * Cleanup all connections.
+ *
+ * TODO: Cleanup only a specified connection passed as a parameter.
+ *
+ * @param tearDown true if the underlying DataConnection should be disconnected.
+ * @param reason for the clean up.
*/
private void cleanUpConnection(boolean tearDown, String reason) {
if (DBG) log("cleanUpConnection: reason: " + reason);
@@ -381,7 +297,7 @@
// Clear the reconnect alarm, if set.
if (mReconnectIntent != null) {
AlarmManager am =
- (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
am.cancel(mReconnectIntent);
mReconnectIntent = null;
}
@@ -390,11 +306,12 @@
notifyDataAvailability(reason);
boolean notificationDeferred = false;
- for (DataConnection conn : dataConnectionList) {
+ for (DataConnection conn : mDataConnections.values()) {
if(conn != null) {
if (tearDown) {
if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
- conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason));
+ conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
+ conn.getDataConnectionId(), 0, reason));
notificationDeferred = true;
} else {
if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
@@ -413,10 +330,9 @@
}
private CdmaDataConnection findFreeDataConnection() {
- for (DataConnection connBase : dataConnectionList) {
- CdmaDataConnection conn = (CdmaDataConnection) connBase;
- if (conn.isInactive()) {
- return conn;
+ for (DataConnection dc : mDataConnections.values()) {
+ if (dc.isInactive()) {
+ return (CdmaDataConnection) dc;
}
}
return null;
@@ -430,7 +346,8 @@
return false;
}
- mActiveDataConnection = conn;
+ /** TODO: We probably want the connection being setup to a parameter passed around */
+ mPendingDataConnection = conn;
String[] types;
if (mRequestedApnType.equals(Phone.APN_TYPE_DUN)) {
types = new String[1];
@@ -458,28 +375,31 @@
}
private void resetPollStats() {
- txPkts = -1;
- rxPkts = -1;
- sentSinceLastRecv = 0;
- netStatPollPeriod = POLL_NETSTAT_MILLIS;
+ mTxPkts = -1;
+ mRxPkts = -1;
+ mSentSinceLastRecv = 0;
+ mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
mNoRecvPollCount = 0;
}
+ @Override
protected void startNetStatPoll() {
- if (state == State.CONNECTED && netStatPollEnabled == false) {
- Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
+ if (mState == State.CONNECTED && mNetStatPollEnabled == false) {
+ log("[DataConnection] Start poll NetStat");
resetPollStats();
- netStatPollEnabled = true;
+ mNetStatPollEnabled = true;
mPollNetStat.run();
}
}
+ @Override
protected void stopNetStatPoll() {
- netStatPollEnabled = false;
+ mNetStatPollEnabled = false;
removeCallbacks(mPollNetStat);
- Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
+ log("[DataConnection] Stop poll NetStat");
}
+ @Override
protected void restartRadio() {
if (DBG) log("Cleanup connection and wait " +
(TIME_DELAYED_TO_RESTART_RADIO / 1000) + "s to restart radio");
@@ -496,73 +416,73 @@
Activity newActivity;
- preTxPkts = txPkts;
- preRxPkts = rxPkts;
+ preTxPkts = mTxPkts;
+ preRxPkts = mRxPkts;
- txPkts = TrafficStats.getMobileTxPackets();
- rxPkts = TrafficStats.getMobileRxPackets();
+ mTxPkts = TrafficStats.getMobileTxPackets();
+ mRxPkts = TrafficStats.getMobileRxPackets();
- //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+ //log("rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
- if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
- sent = txPkts - preTxPkts;
- received = rxPkts - preRxPkts;
+ if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
+ sent = mTxPkts - preTxPkts;
+ received = mRxPkts - preRxPkts;
if ( sent > 0 && received > 0 ) {
- sentSinceLastRecv = 0;
+ mSentSinceLastRecv = 0;
newActivity = Activity.DATAINANDOUT;
} else if (sent > 0 && received == 0) {
- if (phone.getState() == Phone.State.IDLE) {
- sentSinceLastRecv += sent;
+ if (mPhone.getState() == Phone.State.IDLE) {
+ mSentSinceLastRecv += sent;
} else {
- sentSinceLastRecv = 0;
+ mSentSinceLastRecv = 0;
}
newActivity = Activity.DATAOUT;
} else if (sent == 0 && received > 0) {
- sentSinceLastRecv = 0;
+ mSentSinceLastRecv = 0;
newActivity = Activity.DATAIN;
} else if (sent == 0 && received == 0) {
- newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE;
+ newActivity = (mActivity == Activity.DORMANT) ? mActivity : Activity.NONE;
} else {
- sentSinceLastRecv = 0;
- newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE;
+ mSentSinceLastRecv = 0;
+ newActivity = (mActivity == Activity.DORMANT) ? mActivity : Activity.NONE;
}
- if (activity != newActivity) {
- activity = newActivity;
- phone.notifyDataActivity();
+ if (mActivity != newActivity && mIsScreenOn) {
+ mActivity = newActivity;
+ mPhone.notifyDataActivity();
}
}
- if (sentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
+ if (mSentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
// Packets sent without ack exceeded threshold.
if (mNoRecvPollCount == 0) {
EventLog.writeEvent(
EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
- sentSinceLastRecv);
+ mSentSinceLastRecv);
}
if (mNoRecvPollCount < NO_RECV_POLL_LIMIT) {
mNoRecvPollCount++;
// Slow down the poll interval to let things happen
- netStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS;
+ mNetStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS;
} else {
- if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
+ if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) +
" pkts since last received");
// We've exceeded the threshold. Restart the radio.
- netStatPollEnabled = false;
+ mNetStatPollEnabled = false;
stopNetStatPoll();
restartRadio();
EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, NO_RECV_POLL_LIMIT);
}
} else {
mNoRecvPollCount = 0;
- netStatPollPeriod = POLL_NETSTAT_MILLIS;
+ mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
}
- if (netStatPollEnabled) {
- mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
+ if (mNetStatPollEnabled) {
+ mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod);
}
}
};
@@ -594,7 +514,7 @@
}
private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
- if (state == State.FAILED) {
+ if (mState == State.FAILED) {
/**
* For now With CDMA we never try to reconnect on
* error and instead just continue to retry
@@ -602,15 +522,15 @@
* TODO: Make this configurable?
*/
int nextReconnectDelay = mRetryMgr.getRetryTimer();
- Log.d(LOG_TAG, "Data Connection activate failed. Scheduling next attempt for "
+ log("Data Connection activate failed. Scheduling next attempt for "
+ (nextReconnectDelay / 1000) + "s");
AlarmManager am =
- (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(INTENT_RECONNECT_ALARM);
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
mReconnectIntent = PendingIntent.getBroadcast(
- phone.getContext(), 0, intent, 0);
+ mPhone.getContext(), 0, intent, 0);
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + nextReconnectDelay,
mReconnectIntent);
@@ -618,7 +538,7 @@
mRetryMgr.increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
- Log.d(LOG_TAG,"NOT Posting Data Connection Unavailable notification "
+ log("NOT Posting Data Connection Unavailable notification "
+ "-- likely transient error");
} else {
notifyNoData(lastFailCauseCode);
@@ -639,14 +559,14 @@
}
protected void onRecordsLoaded() {
- if (state == State.FAILED) {
+ if (mState == State.FAILED) {
cleanUpConnection(false, null);
}
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
}
protected void onNVReady() {
- if (state == State.FAILED) {
+ if (mState == State.FAILED) {
cleanUpConnection(false, null);
}
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
@@ -657,12 +577,13 @@
*/
@Override
protected void onEnableNewApn() {
- cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
+ cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
}
/**
* @override com.android.internal.telephony.DataConnectionTracker
*/
+ @Override
protected boolean onTrySetupData(String reason) {
return trySetupData(reason);
}
@@ -670,6 +591,7 @@
/**
* @override com.android.internal.telephony.DataConnectionTracker
*/
+ @Override
protected void onRoamingOff() {
trySetupData(Phone.REASON_ROAMING_OFF);
}
@@ -677,6 +599,7 @@
/**
* @override com.android.internal.telephony.DataConnectionTracker
*/
+ @Override
protected void onRoamingOn() {
if (getDataOnRoamingEnabled()) {
trySetupData(Phone.REASON_ROAMING_ON);
@@ -689,19 +612,20 @@
/**
* @override com.android.internal.telephony.DataConnectionTracker
*/
+ @Override
protected void onRadioAvailable() {
- if (phone.getSimulatedRadioControl() != null) {
+ if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
setState(State.CONNECTED);
notifyDataConnection(null);
- Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
+ log("We're on the simulator; assuming data is connected");
}
notifyDataAvailability(null);
- if (state != State.IDLE) {
+ if (mState != State.IDLE) {
cleanUpConnection(true, null);
}
}
@@ -709,13 +633,14 @@
/**
* @override com.android.internal.telephony.DataConnectionTracker
*/
+ @Override
protected void onRadioOffOrNotAvailable() {
mRetryMgr.resetRetryCount();
- if (phone.getSimulatedRadioControl() != null) {
+ if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
- Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
+ log("We're on the simulator; assuming radio off is meaningless");
} else {
if (DBG) log("Radio is off and clean up all connection");
cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
@@ -725,6 +650,7 @@
/**
* @override com.android.internal.telephony.DataConnectionTracker
*/
+ @Override
protected void onDataSetupComplete(AsyncResult ar) {
String reason = null;
if (ar.userObj instanceof String) {
@@ -733,8 +659,8 @@
if (ar.exception == null) {
// TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
- mLinkProperties = getLinkProperties(mActiveDataConnection);
- mLinkCapabilities = getLinkCapabilities(mActiveDataConnection);
+ mLinkProperties = getLinkProperties(mPendingDataConnection);
+ mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
// everything is setup
notifyDefaultData(reason);
@@ -754,8 +680,9 @@
/**
* Called when EVENT_DISCONNECT_DONE is received.
*/
- protected void onDisconnectDone(AsyncResult ar) {
- if(DBG) log("EVENT_DISCONNECT_DONE");
+ @Override
+ protected void onDisconnectDone(int connId, AsyncResult ar) {
+ if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId);
String reason = null;
if (ar.userObj instanceof String) {
reason = (String) ar.userObj;
@@ -799,8 +726,9 @@
/**
* @override com.android.internal.telephony.DataConnectionTracker
*/
+ @Override
protected void onVoiceCallStarted() {
- if (state == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+ if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
notifyDataAvailability(Phone.REASON_VOICE_CALL_STARTED);
@@ -810,8 +738,9 @@
/**
* @override com.android.internal.telephony.DataConnectionTracker
*/
+ @Override
protected void onVoiceCallEnded() {
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
startNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
@@ -827,39 +756,49 @@
}
}
- /**
- * @override com.android.internal.telephony.DataConnectionTracker
- */
+ @Override
protected void onCleanUpConnection(boolean tearDown, String reason) {
cleanUpConnection(tearDown, reason);
}
private void createAllDataConnectionList() {
- dataConnectionList = new ArrayList<DataConnection>();
CdmaDataConnection dataConn;
- for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
- dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone);
- dataConnectionList.add(dataConn);
- }
+ /** TODO: Use one retry manager for all connections for now */
+ RetryManager rm = mRetryMgr;
+ if (!rm.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
+ if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+ // Should never happen, log an error and default to a simple linear sequence.
+ log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+ + DEFAULT_DATA_RETRY_CONFIG);
+ rm.configure(20, 2000, 1000);
+ }
+ }
+
+ for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
+ int id = mUniqueIdGenerator.getAndIncrement();
+
+ dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm);
+ mDataConnections.put(id, dataConn);
+ }
}
private void destroyAllDataConnectionList() {
- if(dataConnectionList != null) {
- dataConnectionList.removeAll(dataConnectionList);
+ if(mDataConnections != null) {
+ mDataConnections.clear();
}
}
private void onCdmaDataDetached() {
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
startNetStatPoll();
notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED);
} else {
- if (state == State.FAILED) {
+ if (mState == State.FAILED) {
cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
mRetryMgr.resetRetryCount();
- CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
+ CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.CDMA_DATA_SETUP_FAILED,
loc != null ? loc.getBaseStationId() : -1,
TelephonyManager.getDefault().getNetworkType());
@@ -886,8 +825,8 @@
private void onRestartRadio() {
if (mPendingRestartRadio) {
- Log.d(LOG_TAG, "************TURN OFF RADIO**************");
- phone.mCM.setRadioPower(false, null);
+ log("************TURN OFF RADIO**************");
+ mPhone.mCM.setRadioPower(false, null);
/* Note: no need to call setRadioPower(true). Assuming the desired
* radio power state is still ON (as tracked by ServiceStateTracker),
* ServiceStateTracker will call setRadioPower when it receives the
@@ -900,7 +839,7 @@
}
private void writeEventLogCdmaDataDrop() {
- CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
+ CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.CDMA_DATA_DROP,
loc != null ? loc.getBaseStationId() : -1,
TelephonyManager.getDefault().getNetworkType());
@@ -916,7 +855,7 @@
return;
}
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
boolean isActiveOrDormantConnectionPresent = false;
int connectionState = DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE;
@@ -932,7 +871,7 @@
if (!isActiveOrDormantConnectionPresent) {
// No active or dormant connection
- Log.i(LOG_TAG, "onDataStateChanged: No active connection"
+ log("onDataStateChanged: No active connection"
+ "state is CONNECTED, disconnecting/cleanup");
writeEventLogCdmaDataDrop();
cleanUpConnection(true, null);
@@ -941,42 +880,39 @@
switch (connectionState) {
case DATA_CONNECTION_ACTIVE_PH_LINK_UP:
- Log.v(LOG_TAG, "onDataStateChanged: active=LINK_ACTIVE && CONNECTED, ignore");
- activity = Activity.NONE;
- phone.notifyDataActivity();
+ log("onDataStateChanged: active=LINK_ACTIVE && CONNECTED, ignore");
+ mActivity = Activity.NONE;
+ mPhone.notifyDataActivity();
startNetStatPoll();
break;
case DATA_CONNECTION_ACTIVE_PH_LINK_DOWN:
- Log.v(LOG_TAG, "onDataStateChanged active=LINK_DOWN && CONNECTED, dormant");
- activity = Activity.DORMANT;
- phone.notifyDataActivity();
+ log("onDataStateChanged active=LINK_DOWN && CONNECTED, dormant");
+ mActivity = Activity.DORMANT;
+ mPhone.notifyDataActivity();
stopNetStatPoll();
break;
default:
- Log.v(LOG_TAG, "onDataStateChanged: IGNORE unexpected DataCallState.active="
+ log("onDataStateChanged: IGNORE unexpected DataCallState.active="
+ connectionState);
}
} else {
// TODO: Do we need to do anything?
- Log.i(LOG_TAG, "onDataStateChanged: not connected, state=" + state + " ignoring");
+ log("onDataStateChanged: not connected, state=" + mState + " ignoring");
}
}
- public ArrayList<DataConnection> getAllDataConnections() {
- return dataConnectionList;
- }
-
private void startDelayedRetry(FailCause cause, String reason) {
notifyNoData(cause);
reconnectAfterFail(cause, reason);
}
+ @Override
public void handleMessage (Message msg) {
- if (!phone.mIsTheCurrentActivePhone) {
- Log.d(LOG_TAG, "Ignore CDMA msgs since CDMA phone is inactive");
+ if (!mPhone.mIsTheCurrentActivePhone) {
+ log("Ignore CDMA msgs since CDMA phone is inactive");
return;
}
@@ -1013,7 +949,13 @@
}
}
+ @Override
protected void log(String s) {
Log.d(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
}
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 1572f09..d428099 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -23,6 +23,7 @@
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.RetryManager;
/**
* {@hide}
@@ -53,23 +54,27 @@
private ApnSetting apn;
//***** Constructor
- private GsmDataConnection(GSMPhone phone, String name) {
- super(phone, name);
+ private GsmDataConnection(GSMPhone phone, String name, RetryManager rm) {
+ super(phone, name, rm);
}
/**
* Create the connection object
*
- * @param phone
+ * @param phone the Phone
+ * @param id the connection id
+ * @param rm the RetryManager
* @return GsmDataConnection that was created.
*/
- static GsmDataConnection makeDataConnection(GSMPhone phone) {
+ static GsmDataConnection makeDataConnection(GSMPhone phone, int id, RetryManager rm) {
synchronized (mCountLock) {
mCount += 1;
}
- GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount);
+ GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount, rm);
gsmDc.start();
if (DBG) gsmDc.log("Made " + gsmDc.getName());
+ gsmDc.mId = id;
+ gsmDc.mRetryMgr = rm;
return gsmDc;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 66da6e8..2aca9ad 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -18,27 +18,19 @@
import android.app.AlarmManager;
import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
-import android.net.IConnectivityManager;
-import android.net.NetworkInfo;
import android.net.ProxyProperties;
import android.net.TrafficStats;
import android.net.Uri;
-import android.net.wifi.WifiManager;
import android.os.AsyncResult;
import android.os.Message;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Telephony;
import android.telephony.ServiceState;
@@ -61,6 +53,7 @@
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.HashMap;
/**
* {@hide}
@@ -85,9 +78,6 @@
//***** Instance Variables
- // Indicates baseband will not auto-attach
- private boolean noAutoAttach = false;
-
private boolean mReregisterOnReconnectFailure = false;
private ContentResolver mResolver;
@@ -95,13 +85,12 @@
// Count of PDP reset attempts; reset when we see incoming,
// call reRegisterNetwork, or pingTest succeeds.
private int mPdpResetCount = 0;
- private boolean mIsScreenOn = true;
/** Delay between APN attempts */
protected static final int APN_DELAY_MILLIS = 5000;
//useful for debugging
- boolean failNextConnect = false;
+ boolean mFailNextConnect = false;
/**
* allApns holds all apns for this sim spn, retrieved from
@@ -109,104 +98,49 @@
*
* Create once after simcard info is loaded
*/
- private ArrayList<ApnSetting> allApns = null;
+ private ArrayList<ApnSetting> mAllApns = null;
/**
* waitingApns holds all apns that are waiting to be connected
*
* It is a subset of allApns and has the same format
*/
- private ArrayList<ApnSetting> waitingApns = null;
+ private ArrayList<ApnSetting> mWaitingApns = null;
- private ApnSetting preferredApn = null;
+ private ApnSetting mPreferredApn = null;
/* Currently active APN */
protected ApnSetting mActiveApn;
- /**
- * pdpList holds all the PDP connection, i.e. IP Link in GPRS
- */
- private ArrayList<DataConnection> pdpList;
+ /** The DataConnection being setup */
+ private GsmDataConnection mPendingDataConnection;
- /** Currently active DataConnection */
- private GsmDataConnection mActivePdp;
+ /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
+ private HashMap<String, Integer> mApnToDataConnectionId =
+ new HashMap<String, Integer>();
/** Is packet service restricted by network */
private boolean mIsPsRestricted = false;
//***** Constants
- // TODO: Increase this to match the max number of simultaneous
- // PDP contexts we plan to support.
- /**
- * Pool size of DataConnection objects.
- */
- private static final int PDP_CONNECTION_POOL_SIZE = 1;
-
private static final int POLL_PDP_MILLIS = 5 * 1000;
private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
static final String APN_ID = "apn_id";
private boolean canSetPreferApn = false;
- // for tracking retries on the default APN
- private RetryManager mDefaultRetryManager;
- // for tracking retries on a secondary APN
- private RetryManager mSecondaryRetryManager;
-
- BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
- {
- @Override
- public void onReceive(Context context, Intent intent)
- {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_SCREEN_ON)) {
- mIsScreenOn = true;
- stopNetStatPoll();
- startNetStatPoll();
- } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- mIsScreenOn = false;
- stopNetStatPoll();
- startNetStatPoll();
- } else if (action.equals((INTENT_RECONNECT_ALARM))) {
- Log.d(LOG_TAG, "GPRS reconnect alarm. Previous state was " + state);
-
- String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
- if (state == State.FAILED) {
- Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 0; // tearDown is false
- msg.obj = (String) reason;
- sendMessage(msg);
- }
- sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
- } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- final android.net.NetworkInfo networkInfo = (NetworkInfo)
- intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
- } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
- if (!enabled) {
- // when wifi got disabled, the NETWORK_STATE_CHANGED_ACTION
- // quit and won't report disconnected til next enabling.
- mIsWifiConnected = false;
- }
- }
- }
- };
-
/** Watches for changes to the APN db. */
- private ApnChangeObserver apnObserver;
+ private ApnChangeObserver mApnObserver;
//***** Constructor
GsmDataConnectionTracker(GSMPhone p) {
super(p);
mGsmPhone = p;
+
p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
@@ -220,73 +154,26 @@
p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
- IntentFilter filter = new IntentFilter();
- filter.addAction(INTENT_RECONNECT_ALARM);
- filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-
- // TODO: Why is this registering the phone as the receiver of the intent
- // and not its own handler?
- p.getContext().registerReceiver(mIntentReceiver, filter, null, p);
-
-
mDataConnectionTracker = this;
- mResolver = phone.getContext().getContentResolver();
+ mResolver = mPhone.getContext().getContentResolver();
- apnObserver = new ApnChangeObserver();
+ mApnObserver = new ApnChangeObserver();
p.getContext().getContentResolver().registerContentObserver(
- Telephony.Carriers.CONTENT_URI, true, apnObserver);
+ Telephony.Carriers.CONTENT_URI, true, mApnObserver);
- createAllPdpList();
-
- // This preference tells us 1) initial condition for "dataEnabled",
- // and 2) whether the RIL will setup the baseband to auto-PS attach.
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
- boolean dataEnabledSetting = true;
- try {
- dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
- getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
- } catch (Exception e) {
- // nothing to do - use the old behavior and leave data on
- }
- dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false) &&
- dataEnabledSetting;
- if (dataEnabled[APN_DEFAULT_ID]) {
- enabledCount++;
- }
- noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
-
- if (!mRetryMgr.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
- if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) {
- // Should never happen, log an error and default to a simple linear sequence.
- Log.e(LOG_TAG, "Could not configure using DEFAULT_DATA_RETRY_CONFIG="
- + DEFAULT_DATA_RETRY_CONFIG);
- mRetryMgr.configure(20, 2000, 1000);
- }
- }
-
- mDefaultRetryManager = mRetryMgr;
- mSecondaryRetryManager = new RetryManager();
-
- if (!mSecondaryRetryManager.configure(SystemProperties.get(
- "ro.gsm.2nd_data_retry_config"))) {
- if (!mSecondaryRetryManager.configure(SECONDARY_DATA_RETRY_CONFIG)) {
- // Should never happen, log an error and default to a simple sequence.
- Log.e(LOG_TAG, "Could note configure using SECONDARY_DATA_RETRY_CONFIG="
- + SECONDARY_DATA_RETRY_CONFIG);
- mSecondaryRetryManager.configure("max_retries=3, 333, 333, 333");
- }
- }
+ /** Create the default connection */
+ createDataConnection(Phone.APN_TYPE_DEFAULT);
}
+ @Override
public void dispose() {
+ super.dispose();
+
//Unregister for all events
- phone.mCM.unregisterForAvailable(this);
- phone.mCM.unregisterForOffOrNotAvailable(this);
+ mPhone.mCM.unregisterForAvailable(this);
+ mPhone.mCM.unregisterForOffOrNotAvailable(this);
mGsmPhone.mSIMRecords.unregisterForRecordsLoaded(this);
- phone.mCM.unregisterForDataStateChanged(this);
+ mPhone.mCM.unregisterForDataStateChanged(this);
mGsmPhone.mCT.unregisterForVoiceCallEnded(this);
mGsmPhone.mCT.unregisterForVoiceCallStarted(this);
mGsmPhone.mSST.unregisterForGprsAttached(this);
@@ -296,29 +183,36 @@
mGsmPhone.mSST.unregisterForPsRestrictedEnabled(this);
mGsmPhone.mSST.unregisterForPsRestrictedDisabled(this);
- phone.getContext().unregisterReceiver(this.mIntentReceiver);
- phone.getContext().getContentResolver().unregisterContentObserver(this.apnObserver);
+ mPhone.getContext().getContentResolver().unregisterContentObserver(this.mApnObserver);
- destroyAllPdpList();
+ destroyDataConnections();
}
+ @Override
protected void finalize() {
- if(DBG) Log.d(LOG_TAG, "GsmDataConnectionTracker finalized");
+ if(DBG) log("finalize");
}
+ @Override
+ protected String getActionIntentReconnectAlarm() {
+ return INTENT_RECONNECT_ALARM;
+ }
+
+ @Override
protected void setState(State s) {
if (DBG) log ("setState: " + s);
- if (state != s) {
- EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, state.toString(), s.toString());
- state = s;
+ if (mState != s) {
+ EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, mState.toString(), s.toString());
+ mState = s;
}
- if (state == State.FAILED) {
- if (waitingApns != null)
- waitingApns.clear(); // when teardown the connection and set to IDLE
+ if (mState == State.FAILED) {
+ if (mWaitingApns != null)
+ mWaitingApns.clear(); // when tear down the connection and set to IDLE
}
}
+ @Override
public String[] getActiveApnTypes() {
String[] result;
if (mActiveApn != null) {
@@ -330,6 +224,7 @@
return result;
}
+ @Override
protected String getActiveApnString() {
String result = null;
if (mActiveApn != null) {
@@ -347,15 +242,16 @@
*
* @return false while no data connection if all above requirements are met.
*/
+ @Override
public boolean isDataConnectionAsDesired() {
- boolean roaming = phone.getServiceState().getRoaming();
+ boolean roaming = mPhone.getServiceState().getRoaming();
if (mGsmPhone.mSIMRecords.getRecordsLoaded() &&
mGsmPhone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
(!roaming || getDataOnRoamingEnabled()) &&
!mIsWifiConnected &&
!mIsPsRestricted ) {
- return (state == State.CONNECTED);
+ return (mState == State.CONNECTED);
}
return true;
}
@@ -372,8 +268,8 @@
return (fetchDunApn() != null);
}
- if (allApns != null) {
- for (ApnSetting apn : allApns) {
+ if (mAllApns != null) {
+ for (ApnSetting apn : mAllApns) {
if (apn.canHandleType(type)) {
return true;
}
@@ -382,14 +278,6 @@
return false;
}
- /**
- * Formerly this method was ArrayList<GsmDataConnection> getAllPdps()
- */
- public ArrayList<DataConnection> getAllDataConnections() {
- ArrayList<DataConnection> pdps = (ArrayList<DataConnection>)pdpList.clone();
- return pdps;
- }
-
//****** Called from ServiceStateTracker
/**
* Invoked when ServiceStateTracker observes a transition from GPRS
@@ -405,11 +293,11 @@
}
private void onGprsAttached() {
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
startNetStatPoll();
notifyDataConnection(Phone.REASON_GPRS_ATTACHED);
} else {
- if (state == State.FAILED) {
+ if (mState == State.FAILED) {
cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED);
mRetryMgr.resetRetryCount();
}
@@ -417,26 +305,30 @@
}
}
+ @Override
protected boolean isDataAllowed() {
int gprsState = mGsmPhone.mSST.getCurrentGprsState();
boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
- boolean allowed = ((gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach) &&
- mGsmPhone.mSIMRecords.getRecordsLoaded() &&
- phone.getState() == Phone.State.IDLE &&
- mMasterDataEnabled &&
- (!phone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
- !mIsPsRestricted &&
- desiredPowerState);
+ boolean allowed =
+ (gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) &&
+ mGsmPhone.mSIMRecords.getRecordsLoaded() &&
+ mPhone.getState() == Phone.State.IDLE &&
+ mMasterDataEnabled &&
+ (!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
+ !mIsPsRestricted &&
+ desiredPowerState;
if (!allowed && DBG) {
String reason = "";
- if (gprsState != ServiceState.STATE_IN_SERVICE) reason += " - gprs= " + gprsState;
+ if (!((gprsState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
+ reason += " - gprs= " + gprsState;
+ }
if (!mGsmPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded";
- if (phone.getState() != Phone.State.IDLE) {
- reason += " - PhoneState= " + phone.getState();
+ if (mPhone.getState() != Phone.State.IDLE) {
+ reason += " - PhoneState= " + mPhone.getState();
}
if (!mMasterDataEnabled) reason += " - mMasterDataEnabled= false";
- if (phone.getServiceState().getRoaming() && getDataOnRoamingEnabled()) {
+ if (mPhone.getServiceState().getRoaming() && getDataOnRoamingEnabled()) {
reason += " - Roaming";
}
if (mIsPsRestricted) reason += " - mIsPsRestricted= true";
@@ -449,38 +341,38 @@
private boolean trySetupData(String reason) {
if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
- Log.d(LOG_TAG, "[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
+ log("[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
- if (phone.getSimulatedRadioControl() != null) {
+ if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
setState(State.CONNECTED);
notifyDataConnection(reason);
- Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected");
+ log("(fix?) We're on the simulator; assuming data is connected");
return true;
}
int gprsState = mGsmPhone.mSST.getCurrentGprsState();
boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
- if (((state == State.IDLE) || (state == State.SCANNING)) &&
+ if (((mState == State.IDLE) || (mState == State.SCANNING)) &&
isDataAllowed() && getAnyDataEnabled()) {
- if (state == State.IDLE) {
- waitingApns = buildWaitingApns();
- if (waitingApns.isEmpty()) {
+ if (mState == State.IDLE) {
+ mWaitingApns = buildWaitingApns(mRequestedApnType);
+ if (mWaitingApns.isEmpty()) {
if (DBG) log("No APN found");
notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
notifyOffApnsOfAvailability(reason, false);
return false;
} else {
- log ("Create from allApns : " + apnListToString(allApns));
+ log ("Create from allApns : " + apnListToString(mAllApns));
}
}
if (DBG) {
- log ("Setup waitngApns : " + apnListToString(waitingApns));
+ log ("Setup waitngApns : " + apnListToString(mWaitingApns));
}
boolean retValue = setupData(reason);
notifyOffApnsOfAvailability(reason, retValue);
@@ -492,13 +384,12 @@
}
/**
- * If tearDown is true, this only tears down a CONNECTED session. Presently,
- * there is no mechanism for abandoning an INITING/CONNECTING session,
- * but would likely involve cancelling pending async requests or
- * setting a flag or new state to ignore them when they came in
- * @param tearDown true if the underlying GsmDataConnection should be
- * disconnected.
- * @param reason reason for the clean up.
+ * Cleanup all connections.
+ *
+ * TODO: Cleanup only a specified connection passed as a parameter.
+ *
+ * @param tearDown true if the underlying DataConnection should be disconnected.
+ * @param reason for the clean up.
*/
private void cleanUpConnection(boolean tearDown, String reason) {
if (DBG) log("Clean up connection due to " + reason);
@@ -506,7 +397,7 @@
// Clear the reconnect alarm, if set.
if (mReconnectIntent != null) {
AlarmManager am =
- (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
am.cancel(mReconnectIntent);
mReconnectIntent = null;
}
@@ -514,10 +405,11 @@
setState(State.DISCONNECTING);
boolean notificationDeferred = false;
- for (DataConnection conn : pdpList) {
+ for (DataConnection conn : mDataConnections.values()) {
if (tearDown) {
if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
- conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason));
+ conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
+ conn.getDataConnectionId(), 0, reason));
notificationDeferred = true;
} else {
if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
@@ -575,51 +467,49 @@
return result;
}
- private GsmDataConnection findFreePdp() {
- for (DataConnection conn : pdpList) {
- GsmDataConnection pdp = (GsmDataConnection) conn;
- if (pdp.isInactive()) {
- return pdp;
+ private GsmDataConnection findFreeDataConnection() {
+ for (DataConnection dc : mDataConnections.values()) {
+ if (dc.isInactive()) {
+ log("found free GsmDataConnection");
+ return (GsmDataConnection) dc;
}
}
+ log("NO free GsmDataConnection");
return null;
}
private boolean setupData(String reason) {
ApnSetting apn;
- GsmDataConnection pdp;
+ GsmDataConnection gdc;
apn = getNextApn();
if (apn == null) return false;
- pdp = findFreePdp();
- if (pdp == null) {
+ gdc = findFreeDataConnection();
+ if (gdc == null) {
if (DBG) log("setupData: No free GsmDataConnection found!");
return false;
}
mActiveApn = apn;
- mActivePdp = pdp;
+ mPendingDataConnection = gdc;
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason;
- pdp.connect(msg, apn);
+ gdc.connect(msg, apn);
setState(State.INITING);
notifyDataConnection(reason);
return true;
}
- private boolean
- pdpStatesHasCID (ArrayList<DataCallState> states, int cid) {
+ private boolean dataCallStatesHasCID (ArrayList<DataCallState> states, int cid) {
for (int i = 0, s = states.size() ; i < s ; i++) {
if (states.get(i).cid == cid) return true;
}
-
return false;
}
- private boolean
- pdpStatesHasActiveCID (ArrayList<DataCallState> states, int cid) {
+ private boolean dataCallStatesHasActiveCID (ArrayList<DataCallState> states, int cid) {
for (int i = 0, s = states.size() ; i < s ; i++) {
if ((states.get(i).cid == cid) && (states.get(i).active != 0)) {
return true;
@@ -635,7 +525,7 @@
private void onApnChanged() {
boolean isConnected;
- isConnected = (state != State.IDLE && state != State.FAILED);
+ isConnected = (mState != State.IDLE && mState != State.FAILED);
// The "current" may no longer be valid. MMS depends on this to send properly.
mGsmPhone.updateCurrentCarrierInProvider();
@@ -643,7 +533,7 @@
// TODO: It'd be nice to only do this if the changed entrie(s)
// match the current operator.
createAllApnList();
- if (state != State.DISCONNECTING) {
+ if (mState != State.DISCONNECTING) {
cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
if (!isConnected) {
// reset reconnect timer
@@ -660,10 +550,10 @@
* via an unsolicited response (which could have happened at any
* previous state
*/
- protected void onPdpStateChanged (AsyncResult ar, boolean explicitPoll) {
- ArrayList<DataCallState> pdpStates;
+ private void onDataStateChanged (AsyncResult ar, boolean explicitPoll) {
+ ArrayList<DataCallState> dataCallStates;
- pdpStates = (ArrayList<DataCallState>)(ar.result);
+ dataCallStates = (ArrayList<DataCallState>)(ar.result);
if (ar.exception != null) {
// This is probably "radio not available" or something
@@ -672,42 +562,42 @@
return;
}
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
// The way things are supposed to work, the PDP list
// should not contain the CID after it disconnects.
// However, the way things really work, sometimes the PDP
// context is still listed with active = false, which
// makes it hard to distinguish an activating context from
// an activated-and-then deactivated one.
- if (!pdpStatesHasCID(pdpStates, cidActive)) {
+ if (!dataCallStatesHasCID(dataCallStates, mCidActive)) {
// It looks like the PDP context has deactivated.
// Tear everything down and try to reconnect.
- Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");
+ log("PDP connection has dropped. Reconnecting");
// Add an event log when the network drops PDP
- GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+ GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
loc != null ? loc.getCid() : -1,
TelephonyManager.getDefault().getNetworkType());
cleanUpConnection(true, null);
return;
- } else if (!pdpStatesHasActiveCID(pdpStates, cidActive)) {
+ } else if (!dataCallStatesHasActiveCID(dataCallStates, mCidActive)) {
// Here, we only consider this authoritative if we asked for the
// PDP list. If it was an unsolicited response, we poll again
// to make sure everyone agrees on the initial state.
if (!explicitPoll) {
// We think it disconnected but aren't sure...poll from our side
- phone.mCM.getPDPContextList(
+ mPhone.mCM.getPDPContextList(
this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
} else {
- Log.i(LOG_TAG, "PDP connection has dropped (active=false case). "
+ log("PDP connection has dropped (active=false case). "
+ " Reconnecting");
// Log the network drop on the event log.
- GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+ GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
loc != null ? loc.getCid() : -1,
TelephonyManager.getDefault().getNetworkType());
@@ -734,38 +624,26 @@
mActiveApn = null;
}
- /**
- * This is a kludge to deal with the fact that
- * the PDP state change notification doesn't always work
- * with certain RIL impl's/basebands
- *
- */
- private void startPeriodicPdpPoll() {
- removeMessages(EVENT_POLL_PDP);
-
- sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
- }
-
private void resetPollStats() {
- txPkts = -1;
- rxPkts = -1;
- sentSinceLastRecv = 0;
- netStatPollPeriod = POLL_NETSTAT_MILLIS;
+ mTxPkts = -1;
+ mRxPkts = -1;
+ mSentSinceLastRecv = 0;
+ mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
mNoRecvPollCount = 0;
}
private void doRecovery() {
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
int maxPdpReset = Settings.Secure.getInt(mResolver,
Settings.Secure.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
DEFAULT_MAX_PDP_RESET_FAIL);
if (mPdpResetCount < maxPdpReset) {
mPdpResetCount++;
- EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, sentSinceLastRecv);
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
cleanUpConnection(true, Phone.REASON_PDP_RESET);
} else {
mPdpResetCount = 0;
- EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, sentSinceLastRecv);
+ EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
mGsmPhone.mSST.reRegisterNetwork(null);
}
// TODO: Add increasingly drastic recovery steps, eg,
@@ -773,23 +651,26 @@
}
}
+ @Override
protected void startNetStatPoll() {
- if (state == State.CONNECTED && mPingTestActive == false && netStatPollEnabled == false) {
- Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
+ if (mState == State.CONNECTED && mPingTestActive == false && mNetStatPollEnabled == false) {
+ log("[DataConnection] Start poll NetStat");
resetPollStats();
- netStatPollEnabled = true;
+ mNetStatPollEnabled = true;
mPollNetStat.run();
}
}
+ @Override
protected void stopNetStatPoll() {
- netStatPollEnabled = false;
+ mNetStatPollEnabled = false;
removeCallbacks(mPollNetStat);
- Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
+ log("[DataConnection] Stop poll NetStat");
}
+ @Override
protected void restartRadio() {
- Log.d(LOG_TAG, "************TURN OFF RADIO**************");
+ log("************TURN OFF RADIO**************");
cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
mGsmPhone.mSST.powerOffRadioSafely();
/* Note: no need to call setRadioPower(true). Assuming the desired
@@ -813,43 +694,43 @@
Activity newActivity;
- preTxPkts = txPkts;
- preRxPkts = rxPkts;
+ preTxPkts = mTxPkts;
+ preRxPkts = mRxPkts;
- txPkts = TrafficStats.getMobileTxPackets();
- rxPkts = TrafficStats.getMobileRxPackets();
+ mTxPkts = TrafficStats.getMobileTxPackets();
+ mRxPkts = TrafficStats.getMobileRxPackets();
- //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+ //log("rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
- if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
- sent = txPkts - preTxPkts;
- received = rxPkts - preRxPkts;
+ if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
+ sent = mTxPkts - preTxPkts;
+ received = mRxPkts - preRxPkts;
if ( sent > 0 && received > 0 ) {
- sentSinceLastRecv = 0;
+ mSentSinceLastRecv = 0;
newActivity = Activity.DATAINANDOUT;
mPdpResetCount = 0;
} else if (sent > 0 && received == 0) {
- if (phone.getState() == Phone.State.IDLE) {
- sentSinceLastRecv += sent;
+ if (mPhone.getState() == Phone.State.IDLE) {
+ mSentSinceLastRecv += sent;
} else {
- sentSinceLastRecv = 0;
+ mSentSinceLastRecv = 0;
}
newActivity = Activity.DATAOUT;
} else if (sent == 0 && received > 0) {
- sentSinceLastRecv = 0;
+ mSentSinceLastRecv = 0;
newActivity = Activity.DATAIN;
mPdpResetCount = 0;
} else if (sent == 0 && received == 0) {
newActivity = Activity.NONE;
} else {
- sentSinceLastRecv = 0;
+ mSentSinceLastRecv = 0;
newActivity = Activity.NONE;
}
- if (activity != newActivity && mIsScreenOn) {
- activity = newActivity;
- phone.notifyDataActivity();
+ if (mActivity != newActivity && mIsScreenOn) {
+ mActivity = newActivity;
+ mPhone.notifyDataActivity();
}
}
@@ -857,11 +738,11 @@
Settings.Secure.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
NUMBER_SENT_PACKETS_OF_HANG);
- if (sentSinceLastRecv >= watchdogTrigger) {
+ if (mSentSinceLastRecv >= watchdogTrigger) {
// we already have NUMBER_SENT_PACKETS sent without ack
if (mNoRecvPollCount == 0) {
EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
- sentSinceLastRecv);
+ mSentSinceLastRecv);
}
int noRecvPollLimit = Settings.Secure.getInt(mResolver,
@@ -871,21 +752,22 @@
// It's possible the PDP context went down and we weren't notified.
// Start polling the context list in an attempt to recover.
if (DBG) log("no DATAIN in a while; polling PDP");
- phone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+ mPhone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
mNoRecvPollCount++;
// Slow down the poll interval to let things happen
- netStatPollPeriod = Settings.Secure.getInt(mResolver,
+ mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
POLL_NETSTAT_SLOW_MILLIS);
} else {
- if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
+ if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) +
" pkts since last received");
// We've exceeded the threshold. Run ping test as a final check;
// it will proceed with recovery if ping fails.
stopNetStatPoll();
Thread pingTest = new Thread() {
+ @Override
public void run() {
runPingTest();
}
@@ -896,17 +778,17 @@
} else {
mNoRecvPollCount = 0;
if (mIsScreenOn) {
- netStatPollPeriod = Settings.Secure.getInt(mResolver,
+ mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
Settings.Secure.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS);
} else {
- netStatPollPeriod = Settings.Secure.getInt(mResolver,
+ mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
Settings.Secure.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
POLL_NETSTAT_SCREEN_OFF_MILLIS);
}
}
- if (netStatPollEnabled) {
- mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
+ if (mNetStatPollEnabled) {
+ mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod);
}
}
};
@@ -925,9 +807,9 @@
status = p.waitFor();
}
} catch (IOException e) {
- Log.w(LOG_TAG, "ping failed: IOException");
+ loge("ping failed: IOException");
} catch (Exception e) {
- Log.w(LOG_TAG, "exception trying to ping");
+ loge("exception trying to ping");
}
if (status == 0) {
@@ -968,7 +850,8 @@
}
private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
- if (state == State.FAILED) {
+ if (mState == State.FAILED) {
+ /** TODO: Retrieve retry manager from connection itself */
if (!mRetryMgr.isRetryNeeded()) {
if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
// if no more retries on a secondary APN attempt, tell the world and revert.
@@ -977,11 +860,11 @@
return;
}
if (mReregisterOnReconnectFailure) {
- // We've re-registerd once now just retry forever.
+ // We've re-registered once now just retry forever.
mRetryMgr.retryForeverUsingLastTimeout();
} else {
// Try to re-register to the network.
- Log.d(LOG_TAG, "PDP activate failed, Reregistering to the network");
+ log("PDP activate failed, Reregistering to the network");
mReregisterOnReconnectFailure = true;
mGsmPhone.mSST.reRegisterNetwork(null);
mRetryMgr.resetRetryCount();
@@ -990,15 +873,15 @@
}
int nextReconnectDelay = mRetryMgr.getRetryTimer();
- Log.d(LOG_TAG, "PDP activate failed. Scheduling next attempt for "
+ log("PDP activate failed. Scheduling next attempt for "
+ (nextReconnectDelay / 1000) + "s");
AlarmManager am =
- (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(INTENT_RECONNECT_ALARM);
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
mReconnectIntent = PendingIntent.getBroadcast(
- phone.getContext(), 0, intent, 0);
+ mPhone.getContext(), 0, intent, 0);
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + nextReconnectDelay,
mReconnectIntent);
@@ -1006,7 +889,7 @@
mRetryMgr.increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
- Log.d(LOG_TAG,"NOT Posting GPRS Unavailable notification "
+ log("NOT Posting GPRS Unavailable notification "
+ "-- likely transient error");
} else {
notifyNoData(lastFailCauseCode);
@@ -1018,9 +901,9 @@
setState(State.FAILED);
}
- protected void onRecordsLoaded() {
+ private void onRecordsLoaded() {
createAllApnList();
- if (state == State.FAILED) {
+ if (mState == State.FAILED) {
cleanUpConnection(false, null);
}
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
@@ -1028,19 +911,29 @@
@Override
protected void onEnableNewApn() {
+ log("onEnableNewApn E");
// change our retry manager to use the appropriate numbers for the new APN
if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
- mRetryMgr = mDefaultRetryManager;
+ log("onEnableNewApn default type");
+ mRetryMgr = mPendingDataConnection.getRetryMgr();
+ mRetryMgr.resetRetryCount();
+ } else if (mApnToDataConnectionId.get(mRequestedApnType) == null) {
+ log("onEnableNewApn mRequestedApnType=" + mRequestedApnType +
+ " missing, make a new connection");
+ int id = createDataConnection(mRequestedApnType);
+ mRetryMgr = mDataConnections.get(id).getRetryMgr();
+ mRetryMgr.resetRetryCount();
} else {
- mRetryMgr = mSecondaryRetryManager;
+ log("oneEnableNewApn connection already exists, nothing to setup");
}
- mRetryMgr.resetRetryCount();
// TODO: To support simultaneous PDP contexts, this should really only call
// cleanUpConnection if it needs to free up a GsmDataConnection.
cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
+ log("onEnableNewApn X");
}
+ @Override
protected boolean onTrySetupData(String reason) {
return trySetupData(reason);
}
@@ -1060,31 +953,33 @@
}
}
+ @Override
protected void onRadioAvailable() {
- if (phone.getSimulatedRadioControl() != null) {
+ if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
setState(State.CONNECTED);
notifyDataConnection(null);
- Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
+ log("We're on the simulator; assuming data is connected");
}
- if (state != State.IDLE) {
+ if (mState != State.IDLE) {
cleanUpConnection(true, null);
}
}
+ @Override
protected void onRadioOffOrNotAvailable() {
// Make sure our reconnect delay starts at the initial value
// next time the radio comes on
mRetryMgr.resetRetryCount();
mReregisterOnReconnectFailure = false;
- if (phone.getSimulatedRadioControl() != null) {
+ if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
- Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
+ log("We're on the simulator; assuming radio off is meaningless");
} else {
if (DBG) log("Radio is off and clean up all connection");
// TODO: Should we reset mRequestedApnType to "default"?
@@ -1092,7 +987,9 @@
}
}
+ @Override
protected void onDataSetupComplete(AsyncResult ar) {
+ /** TODO: Which connection is completing should be a parameter */
String reason = null;
if (ar.userObj instanceof String) {
reason = (String) ar.userObj;
@@ -1100,10 +997,10 @@
if (ar.exception == null) {
// TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
- mLinkProperties = getLinkProperties(mActivePdp);
- mLinkCapabilities = getLinkCapabilities(mActivePdp);
+ mLinkProperties = getLinkProperties(mPendingDataConnection);
+ mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
- ApnSetting apn = mActivePdp.getApn();
+ ApnSetting apn = mPendingDataConnection.getApn();
if (apn.proxy != null && apn.proxy.length() != 0) {
try {
ProxyProperties proxy = new ProxyProperties();
@@ -1111,11 +1008,11 @@
Integer.parseInt(apn.port)));
mLinkProperties.setHttpProxy(proxy);
} catch (UnknownHostException e) {
- Log.e(LOG_TAG, "UnknownHostException making ProxyProperties: " + e);
+ loge("UnknownHostException making ProxyProperties: " + e);
} catch (SecurityException e) {
- Log.e(LOG_TAG, "SecurityException making ProxyProperties: " + e);
+ loge("SecurityException making ProxyProperties: " + e);
} catch (NumberFormatException e) {
- Log.e(LOG_TAG, "NumberFormatException making ProxyProperties (" + apn.port +
+ loge("NumberFormatException making ProxyProperties (" + apn.port +
"): " + e);
}
}
@@ -1123,10 +1020,10 @@
// everything is setup
if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
SystemProperties.set("gsm.defaultpdpcontext.active", "true");
- if (canSetPreferApn && preferredApn == null) {
- Log.d(LOG_TAG, "PREFERRED APN is null");
- preferredApn = mActiveApn;
- setPreferredApn(preferredApn.id);
+ if (canSetPreferApn && mPreferredApn == null) {
+ log("PREFERRED APN is null");
+ mPreferredApn = mActiveApn;
+ setPreferredApn(mPreferredApn.id);
}
} else {
SystemProperties.set("gsm.defaultpdpcontext.active", "false");
@@ -1143,13 +1040,14 @@
if(DBG) log("PDP setup failed " + cause);
// Log this failure to the Event Logs.
if (cause.isEventLoggable()) {
- GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+ GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
cause.ordinal(), loc != null ? loc.getCid() : -1,
TelephonyManager.getDefault().getNetworkType());
}
- // No try for permanent failure
+ // Do not retry on permanent failure
+ // TODO: We should not fail permanently if more Apns to try!
if (cause.isPermanentFail()) {
notifyNoData(cause);
notifyDataConnection(Phone.REASON_APN_FAILED);
@@ -1157,8 +1055,8 @@
return;
}
- waitingApns.remove(0);
- if (waitingApns.isEmpty()) {
+ mWaitingApns.remove(0);
+ if (mWaitingApns.isEmpty()) {
// No more to try, start delayed retry
startDelayedRetry(cause, reason);
} else {
@@ -1174,9 +1072,10 @@
/**
* Called when EVENT_DISCONNECT_DONE is received.
*/
- protected void onDisconnectDone(AsyncResult ar) {
+ @Override
+ protected void onDisconnectDone(int connId, AsyncResult ar) {
+ if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId);
String reason = null;
- if(DBG) log("EVENT_DISCONNECT_DONE");
if (ar.userObj instanceof String) {
reason = (String) ar.userObj;
}
@@ -1202,22 +1101,24 @@
}
protected void onPollPdp() {
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
// only poll when connected
- phone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+ mPhone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
}
}
+ @Override
protected void onVoiceCallStarted() {
- if (state == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+ if (mState == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) {
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
}
}
+ @Override
protected void onVoiceCallEnded() {
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
if (!mGsmPhone.mSST.isConcurrentVoiceAndData()) {
startNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
@@ -1234,74 +1135,92 @@
}
}
+ @Override
protected void onCleanUpConnection(boolean tearDown, String reason) {
cleanUpConnection(tearDown, reason);
}
/**
- * Based on the sim operator numeric, create a list for all possible pdps
- * with all apns associated with that pdp
- *
- *
+ * Based on the sim operator numeric, create a list for all possible
+ * Data Connections and setup the preferredApn.
*/
private void createAllApnList() {
- allApns = new ArrayList<ApnSetting>();
+ mAllApns = new ArrayList<ApnSetting>();
String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
if (operator != null) {
String selection = "numeric = '" + operator + "'";
- Cursor cursor = phone.getContext().getContentResolver().query(
+ Cursor cursor = mPhone.getContext().getContentResolver().query(
Telephony.Carriers.CONTENT_URI, null, selection, null, null);
if (cursor != null) {
if (cursor.getCount() > 0) {
- allApns = createApnList(cursor);
- // TODO: Figure out where this fits in. This basically just
- // writes the pap-secrets file. No longer tied to GsmDataConnection
- // object. Not used on current platform (no ppp).
- //GsmDataConnection pdp = pdpList.get(pdp_name);
- //if (pdp != null && pdp.dataLink != null) {
- // pdp.dataLink.setPasswordInfo(cursor);
- //}
+ mAllApns = createApnList(cursor);
}
cursor.close();
}
}
- if (allApns.isEmpty()) {
+ if (mAllApns.isEmpty()) {
if (DBG) log("No APN found for carrier: " + operator);
- preferredApn = null;
+ mPreferredApn = null;
notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
} else {
- preferredApn = getPreferredApn();
- Log.d(LOG_TAG, "Get PreferredAPN");
- if (preferredApn != null && !preferredApn.numeric.equals(operator)) {
- preferredApn = null;
+ mPreferredApn = getPreferredApn();
+ log("Get PreferredAPN");
+ if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
+ mPreferredApn = null;
setPreferredApn(-1);
}
}
}
- private void createAllPdpList() {
- pdpList = new ArrayList<DataConnection>();
- DataConnection pdp;
+ /** Return the id for a new data connection */
+ private int createDataConnection(String apnType) {
+ log("createDataConnection(" + apnType + ") E");
+ RetryManager rm = new RetryManager();
- for (int i = 0; i < PDP_CONNECTION_POOL_SIZE; i++) {
- pdp = GsmDataConnection.makeDataConnection(mGsmPhone);
- pdpList.add(pdp);
- }
+ if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
+ if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
+ if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+ // Should never happen, log an error and default to a simple linear sequence.
+ log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+ + DEFAULT_DATA_RETRY_CONFIG);
+ rm.configure(20, 2000, 1000);
+ }
+ }
+ } else {
+ if (!rm.configure(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
+ if (!rm.configure(SECONDARY_DATA_RETRY_CONFIG)) {
+ // Should never happen, log an error and default to a simple sequence.
+ log("Could note configure using SECONDARY_DATA_RETRY_CONFIG="
+ + SECONDARY_DATA_RETRY_CONFIG);
+ rm.configure("max_retries=3, 333, 333, 333");
+ }
+ }
+ }
+
+ int id = mUniqueIdGenerator.getAndIncrement();
+ DataConnection conn = GsmDataConnection.makeDataConnection(mGsmPhone, id, rm);
+ mDataConnections.put(id, conn);
+ mApnToDataConnectionId.put(apnType, id);
+
+ log("createDataConnection(" + apnType + ") X id=" + id);
+ return id;
}
- private void destroyAllPdpList() {
- if(pdpList != null) {
- GsmDataConnection pdp;
- pdpList.removeAll(pdpList);
+ private void destroyDataConnections() {
+ if(mDataConnections != null) {
+ log("destroyDataConnectionList clear mDataConnectionList");
+ mDataConnections.clear();
+ } else {
+ log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
}
}
private ApnSetting fetchDunApn() {
- Context c = phone.getContext();
+ Context c = mPhone.getContext();
String apnData = Settings.Secure.getString(c.getContentResolver(),
Settings.Secure.TETHER_DUN_APN);
ApnSetting dunSetting = ApnSetting.fromString(apnData);
@@ -1312,14 +1231,16 @@
}
/**
+ * Build a list of APNs to be used to create PDP's.
*
+ * @param requestedApnType
* @return waitingApns list to be used to create PDP
* error when waitingApns.isEmpty()
*/
- private ArrayList<ApnSetting> buildWaitingApns() {
+ private ArrayList<ApnSetting> buildWaitingApns(String requestedApnType) {
ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>();
- if (mRequestedApnType.equals(Phone.APN_TYPE_DUN)) {
+ if (requestedApnType.equals(Phone.APN_TYPE_DUN)) {
ApnSetting dun = fetchDunApn();
if (dun != null) apnList.add(dun);
return apnList;
@@ -1327,24 +1248,24 @@
String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
- if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
- if (canSetPreferApn && preferredApn != null) {
- Log.i(LOG_TAG, "Preferred APN:" + operator + ":"
- + preferredApn.numeric + ":" + preferredApn);
- if (preferredApn.numeric.equals(operator)) {
- Log.i(LOG_TAG, "Waiting APN set to preferred APN");
- apnList.add(preferredApn);
+ if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
+ if (canSetPreferApn && mPreferredApn != null) {
+ log("Preferred APN:" + operator + ":"
+ + mPreferredApn.numeric + ":" + mPreferredApn);
+ if (mPreferredApn.numeric.equals(operator)) {
+ log("Waiting APN set to preferred APN");
+ apnList.add(mPreferredApn);
return apnList;
} else {
setPreferredApn(-1);
- preferredApn = null;
+ mPreferredApn = null;
}
}
}
- if (allApns != null) {
- for (ApnSetting apn : allApns) {
- if (apn.canHandleType(mRequestedApnType)) {
+ if (mAllApns != null) {
+ for (ApnSetting apn : mAllApns) {
+ if (apn.canHandleType(requestedApnType)) {
apnList.add(apn);
}
}
@@ -1357,7 +1278,7 @@
* @return the first apn found in waitingApns, null if none
*/
private ApnSetting getNextApn() {
- ArrayList<ApnSetting> list = waitingApns;
+ ArrayList<ApnSetting> list = mWaitingApns;
ApnSetting apn = null;
if (list != null) {
@@ -1388,7 +1309,7 @@
return;
}
- ContentResolver resolver = phone.getContext().getContentResolver();
+ ContentResolver resolver = mPhone.getContext().getContentResolver();
resolver.delete(PREFERAPN_URI, null, null);
if (pos >= 0) {
@@ -1399,11 +1320,11 @@
}
private ApnSetting getPreferredApn() {
- if (allApns.isEmpty()) {
+ if (mAllApns.isEmpty()) {
return null;
}
- Cursor cursor = phone.getContext().getContentResolver().query(
+ Cursor cursor = mPhone.getContext().getContentResolver().query(
PREFERAPN_URI, new String[] { "_id", "name", "apn" },
null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
@@ -1417,7 +1338,7 @@
int pos;
cursor.moveToFirst();
pos = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID));
- for(ApnSetting p:allApns) {
+ for(ApnSetting p:mAllApns) {
if (p.id == pos && p.canHandleType(mRequestedApnType)) {
cursor.close();
return p;
@@ -1432,11 +1353,12 @@
return null;
}
+ @Override
public void handleMessage (Message msg) {
- if (DBG) Log.d(LOG_TAG,"GSMDataConnTrack handleMessage "+msg);
+ if (DBG) log("GSMDataConnTrack handleMessage "+msg);
if (!mGsmPhone.mIsTheCurrentActivePhone) {
- Log.d(LOG_TAG, "Ignore GSM msgs since GSM phone is inactive");
+ log("Ignore GSM msgs since GSM phone is inactive");
return;
}
@@ -1454,11 +1376,11 @@
break;
case EVENT_DATA_STATE_CHANGED:
- onPdpStateChanged((AsyncResult) msg.obj, false);
+ onDataStateChanged((AsyncResult) msg.obj, false);
break;
case EVENT_GET_PDP_LIST_COMPLETE:
- onPdpStateChanged((AsyncResult) msg.obj, true);
+ onDataStateChanged((AsyncResult) msg.obj, true);
break;
case EVENT_POLL_PDP:
@@ -1486,7 +1408,7 @@
* PDP context and notify us with PDP_CONTEXT_CHANGED.
* But we should stop the network polling and prevent reset PDP.
*/
- Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
+ log("[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
stopNetStatPoll();
mIsPsRestricted = true;
break;
@@ -1496,12 +1418,12 @@
* When PS restrict is removed, we need setup PDP connection if
* PDP connection is down.
*/
- Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
+ log("[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
mIsPsRestricted = false;
- if (state == State.CONNECTED) {
+ if (mState == State.CONNECTED) {
startNetStatPoll();
} else {
- if (state == State.FAILED) {
+ if (mState == State.FAILED) {
cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
mRetryMgr.resetRetryCount();
mReregisterOnReconnectFailure = false;
@@ -1517,7 +1439,13 @@
}
}
+ @Override
protected void log(String s) {
Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
}
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[GsmDataConnectionTracker] " + s);
+ }
}