Merge "Move the padding to the text field in SearchView."
diff --git a/api/current.txt b/api/current.txt
index 1e3d40e..3ea70b7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16037,6 +16037,12 @@
field public static final java.lang.String GROUP_SOURCE_ID = "group_sourceid";
}
+ public static final class ContactsContract.CommonDataKinds.Identity implements android.provider.ContactsContract.DataColumnsWithJoins {
+ field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/identity";
+ field public static final java.lang.String IDENTITY = "data1";
+ field public static final java.lang.String NAMESPACE = "data2";
+ }
+
public static final class ContactsContract.CommonDataKinds.Im implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
method public static final java.lang.CharSequence getProtocolLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getProtocolLabelResource(int);
@@ -22481,12 +22487,14 @@
method public android.graphics.Bitmap getBitmap(android.graphics.Bitmap);
method public android.graphics.SurfaceTexture getSurfaceTexture();
method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
+ method public android.graphics.Matrix getTransform(android.graphics.Matrix);
method public boolean isAvailable();
method public android.graphics.Canvas lockCanvas();
method public android.graphics.Canvas lockCanvas(android.graphics.Rect);
method protected final void onDraw(android.graphics.Canvas);
method public void setOpaque(boolean);
method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
+ method public void setTransform(android.graphics.Matrix);
method public void unlockCanvasAndPost(android.graphics.Canvas);
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index eb9cd21..53fd50d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -260,11 +260,18 @@
*/
public static final int TYPE_MOBILE_CBS = 12;
- /** {@hide} */
- public static final int MAX_RADIO_TYPE = TYPE_MOBILE_CBS;
+ /**
+ * A Wi-Fi p2p connection. Only requesting processes will have access to
+ * the peers connected.
+ * {@hide}
+ */
+ public static final int TYPE_WIFI_P2P = 13;
/** {@hide} */
- public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_CBS;
+ public static final int MAX_RADIO_TYPE = TYPE_WIFI_P2P;
+
+ /** {@hide} */
+ public static final int MAX_NETWORK_TYPE = TYPE_WIFI_P2P;
public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
@@ -303,6 +310,8 @@
return "MOBILE_IMS";
case TYPE_MOBILE_CBS:
return "MOBILE_CBS";
+ case TYPE_WIFI_P2P:
+ return "WIFI_P2P";
default:
return Integer.toString(type);
}
diff --git a/core/java/android/net/DhcpInfoInternal.java b/core/java/android/net/DhcpInfoInternal.java
index 860da0a..9b0a2d7 100644
--- a/core/java/android/net/DhcpInfoInternal.java
+++ b/core/java/android/net/DhcpInfoInternal.java
@@ -100,7 +100,8 @@
if (TextUtils.isEmpty(dns1) == false) {
p.addDns(NetworkUtils.numericToInetAddress(dns1));
} else {
- Log.d(TAG, "makeLinkProperties with empty dns1!");
+ p.addDns(NetworkUtils.numericToInetAddress(serverAddress));
+ Log.d(TAG, "empty dns1, use dhcp server as dns1!");
}
if (TextUtils.isEmpty(dns2) == false) {
p.addDns(NetworkUtils.numericToInetAddress(dns2));
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d867e35..a66fa81 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -6455,6 +6455,37 @@
}
}
}
+
+ /**
+ * A data kind representing an Identity related to the contact.
+ * <p>
+ * This can be used as a signal by the aggregator to combine raw contacts into
+ * contacts, e.g. if two contacts have Identity rows with
+ * the same NAMESPACE and IDENTITY values the aggregator can know that they refer
+ * to the same person.
+ * </p>
+ */
+ public static final class Identity implements DataColumnsWithJoins {
+ /**
+ * This utility class cannot be instantiated
+ */
+ private Identity() {}
+
+ /** MIME type used when storing this in data table. */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/identity";
+
+ /**
+ * The identity string.
+ * <P>Type: TEXT</P>
+ */
+ public static final String IDENTITY = DataColumns.DATA1;
+
+ /**
+ * The namespace of the identity string, e.g. "com.google"
+ * <P>Type: TEXT</P>
+ */
+ public static final String NAMESPACE = DataColumns.DATA2;
+ }
}
/**
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index e586370..cfbb47c 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -151,6 +151,7 @@
static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
SurfaceTexture surface);
+ static native void nSetTextureLayerTransform(int layerId, int matrix);
static native void nDestroyLayer(int layerId);
static native void nDestroyLayerDeferred(int layerId);
static native boolean nCopyLayer(int layerId, int bitmap);
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index 41f16e2..23a7166 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -17,6 +17,7 @@
package android.view;
import android.graphics.Canvas;
+import android.graphics.Matrix;
/**
* An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This
@@ -87,4 +88,11 @@
}
return getCanvas();
}
+
+ /**
+ * Ignored
+ */
+ @Override
+ void setTransform(Matrix matrix) {
+ }
}
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 391d9f4..6c41023 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -17,6 +17,7 @@
package android.view;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
/**
@@ -75,4 +76,9 @@
super.update(width, height, isOpaque);
GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, isOpaque, mSurface);
}
+
+ @Override
+ void setTransform(Matrix matrix) {
+ GLES20Canvas.nSetTextureLayerTransform(mLayer, matrix.native_instance);
+ }
}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index dfb39ae..28389ab 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -18,6 +18,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Matrix;
/**
* A hardware layer can be used to render graphics operations into a hardware
@@ -150,4 +151,11 @@
mHeight = height;
mOpaque = isOpaque;
}
+
+ /**
+ * Sets an optional transform on this layer.
+ *
+ * @param matrix The transform to apply to the layer.
+ */
+ abstract void setTransform(Matrix matrix);
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index f2c3131..a05637d 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -718,7 +718,9 @@
if (!createSurface(holder)) {
return;
}
- setEnabled(true);
+ if (mCanvas != null) {
+ setEnabled(true);
+ }
}
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 53a6bcb..b72222e 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
@@ -104,6 +105,9 @@
private boolean mOpaque = true;
+ private final Matrix mMatrix = new Matrix();
+ private boolean mMatrixChanged;
+
private final Object[] mLock = new Object[0];
private boolean mUpdateLayer;
@@ -312,6 +316,11 @@
applyUpdate();
+ if (mMatrixChanged) {
+ mLayer.setTransform(mMatrix);
+ mMatrixChanged = false;
+ }
+
return mLayer;
}
@@ -358,6 +367,50 @@
}
/**
+ * <p>Sets the transform to associate with this texture view.
+ * The specified transform applies to the underlying surface
+ * texture and does not affect the size or position of the view
+ * itself, only of its content.</p>
+ *
+ * <p>Some transforms might prevent the content from drawing
+ * all the pixels contained within this view's bounds. In such
+ * situations, make sure this texture view is not marked opaque.</p>
+ *
+ * @param transform The transform to apply to the content of
+ * this view.
+ *
+ * @see #getTransform(android.graphics.Matrix)
+ * @see #isOpaque()
+ * @see #setOpaque(boolean)
+ */
+ public void setTransform(Matrix transform) {
+ mMatrix.set(transform);
+ mMatrixChanged = true;
+ invalidate();
+ }
+
+ /**
+ * Returns the transform associated with this texture view.
+ *
+ * @param transform The {@link Matrix} in which to copy the current
+ * transform. Can be null.
+ *
+ * @return The specified matrix if not null or a new {@link Matrix}
+ * instance otherwise.
+ *
+ * @see #setTransform(android.graphics.Matrix)
+ */
+ public Matrix getTransform(Matrix transform) {
+ if (transform == null) {
+ transform = new Matrix();
+ }
+
+ transform.set(mMatrix);
+
+ return transform;
+ }
+
+ /**
* <p>Returns a {@link android.graphics.Bitmap} representation of the content
* of the associated surface texture. If the surface texture is not available,
* this method returns null.</p>
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 70e48ad..2bcb020 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -709,10 +709,14 @@
final WebSettings settings = mWebView.getSettings();
final PackageManager pm = context.getPackageManager();
- mSupportMultiTouch = pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)
+ mSupportMultiTouch =
+ (pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)
+ || pm.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT))
&& settings.supportZoom() && settings.getBuiltInZoomControls();
- mAllowPanAndScale = pm.hasSystemFeature(
- PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
+ mAllowPanAndScale =
+ pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)
+ || pm.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT);
+
if (mSupportMultiTouch && (mScaleDetector == null)) {
mScaleDetector = new ScaleGestureDetector(context, new ScaleDetectorListener());
} else if (!mSupportMultiTouch && (mScaleDetector != null)) {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 267221b..d613921 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -109,6 +109,13 @@
// Divide the view into cells.
final int cellCount = widthSize / mMinCellSize;
final int cellSizeRemaining = widthSize % mMinCellSize;
+
+ if (cellCount == 0) {
+ // Give up, nothing fits.
+ setMeasuredDimension(widthSize, 0);
+ return;
+ }
+
final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;
int cellsRemaining = cellCount;
@@ -213,7 +220,8 @@
}
}
- final int extraPixels = (int) (cellsRemaining * cellSize / expandCount);
+ final int extraPixels = expandCount > 0 ?
+ (int) (cellsRemaining * cellSize / expandCount) : 0;
for (int i = 0; i < childCount; i++) {
if ((smallestItemsAt & (1 << i)) == 0) continue;
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 039c5ba..80c79fd 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -683,6 +683,12 @@
LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
}
+static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
+ Layer* layer, SkMatrix* matrix) {
+
+ layer->getTransform().load(*matrix);
+}
+
static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) {
LayerRenderer::destroyLayer(layer);
}
@@ -827,6 +833,7 @@
{ "nCreateTextureLayer", "(Z[I)I", (void*) android_view_GLES20Canvas_createTextureLayer },
{ "nUpdateTextureLayer", "(IIIZLandroid/graphics/SurfaceTexture;)V",
(void*) android_view_GLES20Canvas_updateTextureLayer },
+ { "nSetTextureLayerTransform", "(II)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform },
{ "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
{ "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
{ "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer },
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3f67d1ba..74989e6 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -116,6 +116,7 @@
<item>"mobile_fota,10,0,2,60000,true"</item>
<item>"mobile_ims,11,0,2,60000,true"</item>
<item>"mobile_cbs,12,0,2,60000,true"</item>
+ <item>"wifi_p2p,13,1,0,-1,true"</item>
</string-array>
<!-- Array of ConnectivityManager.TYPE_xxxx constants for networks that may only
diff --git a/data/fonts/Lohit_Hindi.ttf b/data/fonts/Lohit_Hindi.ttf
new file mode 100644
index 0000000..73caae3
--- /dev/null
+++ b/data/fonts/Lohit_Hindi.ttf
Binary files differ
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 6ac615d..1bee47a 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -46,6 +46,11 @@
</family>
<family>
<fileset>
+ <file>Lohit_Hindi.ttf</file>
+ </fileset>
+ </family>
+ <family>
+ <fileset>
<file>DroidSansFallback.ttf</file>
</fileset>
</family>
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 73fb111..d8c1fa2 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -31,6 +31,7 @@
frameworks/base/data/fonts/DroidSerif-Italic.ttf:system/fonts/DroidSerif-Italic.ttf \
frameworks/base/data/fonts/DroidSerif-BoldItalic.ttf:system/fonts/DroidSerif-BoldItalic.ttf \
frameworks/base/data/fonts/DroidSansMono.ttf:system/fonts/DroidSansMono.ttf \
+ frameworks/base/data/fonts/Lohit_Hindi.ttf:system/fonts/Lohit_Hindi.ttf \
frameworks/base/data/fonts/Clockopia.ttf:system/fonts/Clockopia.ttf \
frameworks/base/data/fonts/DroidSansFallback.ttf:system/fonts/DroidSansFallback.ttf \
frameworks/base/data/fonts/AndroidClock.ttf:system/fonts/AndroidClock.ttf \
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index f13e9bb..e965f14 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -36,6 +36,7 @@
kWhatShutdownCompleted = 'scom',
kWhatFlushCompleted = 'fcom',
kWhatOutputFormatChanged = 'outC',
+ kWhatError = 'erro',
};
ACodec();
@@ -58,7 +59,6 @@
struct OutputPortSettingsChangedState;
struct ExecutingToIdleState;
struct IdleToLoadedState;
- struct ErrorState;
struct FlushingState;
enum {
@@ -102,7 +102,6 @@
sp<OutputPortSettingsChangedState> mOutputPortSettingsChangedState;
sp<ExecutingToIdleState> mExecutingToIdleState;
sp<IdleToLoadedState> mIdleToLoadedState;
- sp<ErrorState> mErrorState;
sp<FlushingState> mFlushingState;
AString mComponentName;
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index dd75497..a8ae5c6 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -203,6 +203,10 @@
return texTransform;
}
+ inline mat4& getTransform() {
+ return transform;
+ }
+
/**
* Bounds of the layer.
*/
@@ -282,6 +286,11 @@
*/
mat4 texTransform;
+ /**
+ * Optional transform.
+ */
+ mat4 transform;
+
}; // struct Layer
}; // namespace uirenderer
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 9fc5131..769c99c 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -51,6 +51,7 @@
data[kTranslateZ] = 0.0f;
data[kPerspective2] = 1.0f;
+ mIsIdentity = true;
mSimpleMatrix = true;
}
@@ -71,14 +72,21 @@
return mSimpleMatrix;
}
+bool Matrix4::isIdentity() {
+ return mIsIdentity;
+}
+
void Matrix4::load(const float* v) {
memcpy(data, v, sizeof(data));
+ // TODO: Do something smarter here
mSimpleMatrix = false;
+ mIsIdentity = false;
}
void Matrix4::load(const Matrix4& v) {
memcpy(data, v.data, sizeof(data));
mSimpleMatrix = v.mSimpleMatrix;
+ mIsIdentity = v.mIsIdentity;
}
void Matrix4::load(const SkMatrix& v) {
@@ -99,6 +107,7 @@
data[kScaleZ] = 1.0f;
mSimpleMatrix = (v.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask));
+ mIsIdentity = v.isIdentity();
}
void Matrix4::copyTo(SkMatrix& v) const {
@@ -148,6 +157,7 @@
v.data[kSkewX] * v.data[kSkewY]) * scale;
mSimpleMatrix = v.mSimpleMatrix;
+ mIsIdentity = v.mIsIdentity;
}
void Matrix4::copyTo(float* v) const {
@@ -166,20 +176,27 @@
for (int i = 0; i < 16; i++) {
data[i] *= v;
}
+ mIsIdentity = false;
}
void Matrix4::loadTranslate(float x, float y, float z) {
loadIdentity();
+
data[kTranslateX] = x;
data[kTranslateY] = y;
data[kTranslateZ] = z;
+
+ mIsIdentity = false;
}
void Matrix4::loadScale(float sx, float sy, float sz) {
loadIdentity();
+
data[kScaleX] = sx;
data[kScaleY] = sy;
data[kScaleZ] = sz;
+
+ mIsIdentity = false;
}
void Matrix4::loadSkew(float sx, float sy) {
@@ -198,6 +215,7 @@
data[kPerspective2] = 1.0f;
mSimpleMatrix = false;
+ mIsIdentity = false;
}
void Matrix4::loadRotate(float angle, float x, float y, float z) {
@@ -238,6 +256,7 @@
data[kScaleZ] = z * z * nc + c;
mSimpleMatrix = false;
+ mIsIdentity = false;
}
void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) {
@@ -262,16 +281,20 @@
}
mSimpleMatrix = u.mSimpleMatrix && v.mSimpleMatrix;
+ mIsIdentity = false;
}
void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) {
loadIdentity();
+
data[kScaleX] = 2.0f / (right - left);
data[kScaleY] = 2.0f / (top - bottom);
data[kScaleZ] = -2.0f / (far - near);
data[kTranslateX] = -(right + left) / (right - left);
data[kTranslateY] = -(top + bottom) / (top - bottom);
data[kTranslateZ] = -(far + near) / (far - near);
+
+ mIsIdentity = false;
}
#define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 2fa6ab7..56fd37d 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -112,6 +112,7 @@
bool isPureTranslate();
bool isSimple();
+ bool isIdentity();
bool changesBounds();
@@ -128,6 +129,7 @@
private:
bool mSimpleMatrix;
+ bool mIsIdentity;
inline float get(int i, int j) const {
return data[i * 4 + j];
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 4864cff..a0f806a 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -627,6 +627,12 @@
void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
float alpha = layer->getAlpha() / 255.0f;
+ mat4& transform = layer->getTransform();
+ if (!transform.isIdentity()) {
+ save(0);
+ mSnapshot->transform->multiply(transform);
+ }
+
setupDraw();
if (layer->getRenderTarget() == GL_TEXTURE_2D) {
setupDrawWithTexture();
@@ -663,6 +669,10 @@
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
finishDrawTexture();
+
+ if (!transform.isIdentity()) {
+ restore();
+ }
}
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index b06f20d..7fb141a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -340,6 +340,11 @@
}
finishFlushIfPossible();
+ } else if (what == ACodec::kWhatError) {
+ LOGE("Received error from %s decoder, aborting playback.",
+ audio ? "audio" : "video");
+
+ mRenderer->queueEOS(audio, UNKNOWN_ERROR);
} else {
CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer);
@@ -358,13 +363,24 @@
int32_t audio;
CHECK(msg->findInt32("audio", &audio));
+ int32_t finalResult;
+ CHECK(msg->findInt32("finalResult", &finalResult));
+
if (audio) {
mAudioEOS = true;
} else {
mVideoEOS = true;
}
- LOGV("reached %s EOS", audio ? "audio" : "video");
+ if (finalResult == ERROR_END_OF_STREAM) {
+ LOGV("reached %s EOS", audio ? "audio" : "video");
+ } else {
+ LOGE("%s track encountered an error (0x%08x)",
+ audio ? "audio" : "video", finalResult);
+
+ notifyListener(
+ MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
+ }
if ((mAudioEOS || mAudioDecoder == NULL)
&& (mVideoEOS || mVideoDecoder == NULL)) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 828e008..35ed43f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -200,6 +200,22 @@
void NuPlayer::Renderer::onDrainAudioQueue() {
for (;;) {
+ if (mAudioQueue.empty()) {
+ break;
+ }
+
+ QueueEntry *entry = &*mAudioQueue.begin();
+
+ if (entry->mBuffer == NULL) {
+ // EOS
+
+ notifyEOS(true /* audio */, entry->mFinalResult);
+
+ mAudioQueue.erase(mAudioQueue.begin());
+ entry = NULL;
+ return;
+ }
+
uint32_t numFramesPlayed;
CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
@@ -213,22 +229,6 @@
break;
}
- if (mAudioQueue.empty()) {
- break;
- }
-
- QueueEntry *entry = &*mAudioQueue.begin();
-
- if (entry->mBuffer == NULL) {
- // EOS
-
- notifyEOS(true /* audio */);
-
- mAudioQueue.erase(mAudioQueue.begin());
- entry = NULL;
- return;
- }
-
if (entry->mOffset == 0) {
int64_t mediaTimeUs;
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
@@ -330,7 +330,7 @@
if (entry->mBuffer == NULL) {
// EOS
- notifyEOS(false /* audio */);
+ notifyEOS(false /* audio */, entry->mFinalResult);
mVideoQueue.erase(mVideoQueue.begin());
entry = NULL;
@@ -352,10 +352,11 @@
notifyPosition();
}
-void NuPlayer::Renderer::notifyEOS(bool audio) {
+void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult) {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatEOS);
notify->setInt32("audio", static_cast<int32_t>(audio));
+ notify->setInt32("finalResult", finalResult);
notify->post();
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 703e971..2713031 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -111,7 +111,7 @@
void onPause();
void onResume();
- void notifyEOS(bool audio);
+ void notifyEOS(bool audio, status_t finalResult);
void notifyFlushComplete(bool audio);
void notifyPosition();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 174ec92..5d91f6a 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -285,21 +285,6 @@
////////////////////////////////////////////////////////////////////////////////
-struct ACodec::ErrorState : public ACodec::BaseState {
- ErrorState(ACodec *codec);
-
-protected:
- virtual bool onMessageReceived(const sp<AMessage> &msg);
- virtual void stateEntered();
-
- virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(ErrorState);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
struct ACodec::FlushingState : public ACodec::BaseState {
FlushingState(ACodec *codec);
@@ -335,7 +320,6 @@
mExecutingToIdleState = new ExecutingToIdleState(this);
mIdleToLoadedState = new IdleToLoadedState(this);
- mErrorState = new ErrorState(this);
mFlushingState = new FlushingState(this);
mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
@@ -594,7 +578,10 @@
ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
ANativeWindowBuffer *buf;
- CHECK_EQ(mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf), 0);
+ if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) {
+ LOGE("dequeueBuffer failed.");
+ return NULL;
+ }
for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
BufferInfo *info =
@@ -1263,10 +1250,12 @@
return false;
}
- LOGE("[%s] ERROR(0x%08lx, 0x%08lx)",
- mCodec->mComponentName.c_str(), data1, data2);
+ LOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
- mCodec->changeState(mCodec->mErrorState);
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatError);
+ notify->setInt32("omx-error", data1);
+ notify->post();
return true;
}
@@ -1595,13 +1584,15 @@
info = mCodec->dequeueBufferFromNativeWindow();
}
- LOGV("[%s] calling fillBuffer %p",
- mCodec->mComponentName.c_str(), info->mBufferID);
+ if (info != NULL) {
+ LOGV("[%s] calling fillBuffer %p",
+ mCodec->mComponentName.c_str(), info->mBufferID);
- CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
- (status_t)OK);
+ CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
+ (status_t)OK);
- info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+ info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+ }
}
break;
}
@@ -1642,6 +1633,7 @@
notify->post();
handled = true;
+ break;
}
case ACodec::kWhatFlush:
@@ -1651,6 +1643,7 @@
notify->post();
handled = true;
+ break;
}
default:
@@ -1696,7 +1689,16 @@
node = NULL;
}
- CHECK(node != NULL);
+ if (node == NULL) {
+ LOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str());
+
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatError);
+ notify->setInt32("omx-error", OMX_ErrorComponentNotFound);
+ notify->post();
+
+ return;
+ }
sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
observer->setNotificationMessage(notify);
@@ -2236,26 +2238,6 @@
////////////////////////////////////////////////////////////////////////////////
-ACodec::ErrorState::ErrorState(ACodec *codec)
- : BaseState(codec) {
-}
-
-bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) {
- return BaseState::onMessageReceived(msg);
-}
-
-void ACodec::ErrorState::stateEntered() {
- LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
-}
-
-bool ACodec::ErrorState::onOMXEvent(
- OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
- LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
ACodec::FlushingState::FlushingState(ACodec *codec)
: BaseState(codec) {
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index f88b311..b60a038 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2850,7 +2850,7 @@
// or orientation sensor disabled
//or case.unspecified
if (mHdmiPlugged) {
- return Surface.ROTATION_0;
+ return mLandscapeRotation;
} else if (mLidOpen == LID_OPEN) {
return mLidOpenRotation;
} else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index a506636..22ce484 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -468,14 +468,10 @@
for (int netType : mPriorityList) {
switch (mNetConfigs[netType].radio) {
case ConnectivityManager.TYPE_WIFI:
- if (DBG) log("Starting Wifi Service.");
- WifiStateTracker wst = new WifiStateTracker();
- WifiService wifiService = new WifiService(context);
- ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
- wifiService.checkAndStartWifi();
- mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
- wst.startMonitoring(context, mHandler);
- break;
+ mNetTrackers[netType] = new WifiStateTracker(netType,
+ mNetConfigs[netType].name);
+ mNetTrackers[netType].startMonitoring(context, mHandler);
+ break;
case ConnectivityManager.TYPE_MOBILE:
mNetTrackers[netType] = new MobileDataStateTracker(netType,
mNetConfigs[netType].name);
@@ -882,15 +878,8 @@
FeatureUser f = new FeatureUser(networkType, feature, binder);
- // TODO - move this into the MobileDataStateTracker
- int usedNetworkType = networkType;
- if(networkType == ConnectivityManager.TYPE_MOBILE) {
- usedNetworkType = convertFeatureToNetworkType(feature);
- if (usedNetworkType < 0) {
- loge("Can't match any netTracker!");
- usedNetworkType = networkType;
- }
- }
+ // TODO - move this into individual networktrackers
+ int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
if (mProtectedNetworks.contains(usedNetworkType)) {
enforceConnectivityInternalPermission();
@@ -900,7 +889,6 @@
if (network != null) {
Integer currentPid = new Integer(getCallingPid());
if (usedNetworkType != networkType) {
- NetworkStateTracker radio = mNetTrackers[networkType];
NetworkInfo ni = network.getNetworkInfo();
if (ni.isAvailable() == false) {
@@ -1046,14 +1034,9 @@
}
}
- // TODO - move to MobileDataStateTracker
- int usedNetworkType = networkType;
- if (networkType == ConnectivityManager.TYPE_MOBILE) {
- usedNetworkType = convertFeatureToNetworkType(feature);
- if (usedNetworkType < 0) {
- usedNetworkType = networkType;
- }
- }
+ // TODO - move to individual network trackers
+ int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
+
tracker = mNetTrackers[usedNetworkType];
if (tracker == null) {
if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
@@ -1780,14 +1763,20 @@
mCurrentLinkProperties[netType] = newLp;
boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
- if (doReset || resetMask != 0 || resetDns) {
+ if (resetMask != 0 || resetDns) {
LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties();
if (linkProperties != null) {
String iface = linkProperties.getInterfaceName();
if (TextUtils.isEmpty(iface) == false) {
- if (doReset || resetMask != 0) {
+ if (resetMask != 0) {
if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
NetworkUtils.resetConnections(iface, resetMask);
+
+ // Tell VPN the interface is down. It is a temporary
+ // but effective fix to make VPN aware of the change.
+ if ((resetMask & NetworkUtils.RESET_IPV4_ADDRESSES) != 0) {
+ mVpn.interfaceStatusChanged(iface, false);
+ }
}
if (resetDns) {
if (DBG) log("resetting DNS cache for " + iface);
@@ -2666,25 +2655,38 @@
Slog.e(TAG, s);
}
- int convertFeatureToNetworkType(String feature){
- int networkType = -1;
- if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
- networkType = ConnectivityManager.TYPE_MOBILE_MMS;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
- networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
- TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
- networkType = ConnectivityManager.TYPE_MOBILE_DUN;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
- networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
- networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
- networkType = ConnectivityManager.TYPE_MOBILE_IMS;
- } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
- networkType = ConnectivityManager.TYPE_MOBILE_CBS;
+ int convertFeatureToNetworkType(int networkType, String feature) {
+ int usedNetworkType = networkType;
+
+ if(networkType == ConnectivityManager.TYPE_MOBILE) {
+ if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
+ usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+ usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
+ TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
+ usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
+ usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
+ usedNetworkType = ConnectivityManager.TYPE_MOBILE_FOTA;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
+ usedNetworkType = ConnectivityManager.TYPE_MOBILE_IMS;
+ } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
+ usedNetworkType = ConnectivityManager.TYPE_MOBILE_CBS;
+ } else {
+ Slog.e(TAG, "Can't match any mobile netTracker!");
+ }
+ } else if (networkType == ConnectivityManager.TYPE_WIFI) {
+ if (TextUtils.equals(feature, "p2p")) {
+ usedNetworkType = ConnectivityManager.TYPE_WIFI_P2P;
+ } else {
+ Slog.e(TAG, "Can't match any wifi netTracker!");
+ }
+ } else {
+ Slog.e(TAG, "Unexpected network type");
}
- return networkType;
+ return usedNetworkType;
}
private static <T> T checkNotNull(T value, String message) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 77d0457..5dd3c5b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -110,6 +110,7 @@
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
WifiP2pService wifiP2p = null;
+ WifiService wifi = null;
IPackageManager pm = null;
Context context = null;
WindowManagerService wm = null;
@@ -309,6 +310,15 @@
Slog.e(TAG, "Failure starting Wi-Fi P2pService", e);
}
+ try {
+ Slog.i(TAG, "Wi-Fi Service");
+ wifi = new WifiService(context);
+ ServiceManager.addService(Context.WIFI_SERVICE, wifi);
+ wifi.checkAndStartWifi();
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting Wi-Fi Service", e);
+ }
+
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(context, networkManagement, networkPolicy);
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index d9da92c..6b65e07 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -265,7 +265,6 @@
// INetworkManagementEventObserver.Stub
@Override
public void interfaceLinkStateChanged(String interfaze, boolean up) {
- interfaceStatusChanged(interfaze, up);
}
// INetworkManagementEventObserver.Stub
@@ -280,6 +279,9 @@
if (mConnection != null) {
mContext.unbindService(mConnection);
mConnection = null;
+ } else if (mLegacyVpnRunner != null) {
+ mLegacyVpnRunner.exit();
+ mLegacyVpnRunner = null;
}
}
}
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 91c5e33..a01c975 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -253,13 +253,6 @@
}
};
- private static final int NOTIFICATION_NONE = 0;
- private static final int NOTIFICATION_MTP = 1;
- private static final int NOTIFICATION_PTP = 2;
- private static final int NOTIFICATION_INSTALLER = 3;
- private static final int NOTIFICATION_ACCESSORY = 4;
- private static final int NOTIFICATION_ADB = 5;
-
public UsbHandler(Looper looper) {
super(looper);
try {
@@ -536,27 +529,18 @@
private void updateUsbNotification() {
if (mNotificationManager == null || !mUseUsbNotification) return;
- int id = NOTIFICATION_NONE;
+ int id = 0;
Resources r = mContext.getResources();
- CharSequence title = null;
if (mConnected) {
if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {
- title = r.getText(
- com.android.internal.R.string.usb_mtp_notification_title);
- id = NOTIFICATION_MTP;
+ id = com.android.internal.R.string.usb_mtp_notification_title;
} else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) {
- title = r.getText(
- com.android.internal.R.string.usb_ptp_notification_title);
- id = NOTIFICATION_PTP;
+ id = com.android.internal.R.string.usb_ptp_notification_title;
} else if (containsFunction(mCurrentFunctions,
UsbManager.USB_FUNCTION_MASS_STORAGE)) {
- title = r.getText(
- com.android.internal.R.string.usb_cd_installer_notification_title);
- id = NOTIFICATION_INSTALLER;
+ id = com.android.internal.R.string.usb_cd_installer_notification_title;
} else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) {
- title = r.getText(
- com.android.internal.R.string.usb_accessory_notification_title);
- id = NOTIFICATION_ACCESSORY;
+ id = com.android.internal.R.string.usb_accessory_notification_title;
} else {
// There is a different notification for USB tethering so we don't need one here
if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
@@ -566,13 +550,14 @@
}
if (id != mUsbNotificationId) {
// clear notification if title needs changing
- if (mUsbNotificationId != NOTIFICATION_NONE) {
+ if (mUsbNotificationId != 0) {
mNotificationManager.cancel(mUsbNotificationId);
- mUsbNotificationId = NOTIFICATION_NONE;
+ mUsbNotificationId = 0;
}
- if (id != NOTIFICATION_NONE) {
+ if (id != 0) {
CharSequence message = r.getText(
com.android.internal.R.string.usb_notification_message);
+ CharSequence title = r.getText(id);
Notification notification = new Notification();
notification.icon = com.android.internal.R.drawable.stat_sys_data_usb;
@@ -600,13 +585,13 @@
private void updateAdbNotification() {
if (mNotificationManager == null) return;
+ final int id = com.android.internal.R.string.adb_active_notification_title;
if (mAdbEnabled && mConnected) {
if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
if (!mAdbNotificationShown) {
Resources r = mContext.getResources();
- CharSequence title = r.getText(
- com.android.internal.R.string.adb_active_notification_title);
+ CharSequence title = r.getText(id);
CharSequence message = r.getText(
com.android.internal.R.string.adb_active_notification_message);
@@ -629,11 +614,11 @@
intent, 0);
notification.setLatestEventInfo(mContext, title, message, pi);
mAdbNotificationShown = true;
- mNotificationManager.notify(NOTIFICATION_ADB, notification);
+ mNotificationManager.notify(id, notification);
}
} else if (mAdbNotificationShown) {
mAdbNotificationShown = false;
- mNotificationManager.cancel(NOTIFICATION_ADB);
+ mNotificationManager.cancel(id);
}
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
index 97e2108..fcb57d9 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -17,6 +17,7 @@
package com.android.test.hwui;
import android.app.Activity;
+import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
@@ -33,6 +34,7 @@
private Camera mCamera;
private TextureView mTextureView;
private FrameLayout mContent;
+ private Matrix mMatrix = new Matrix();
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -82,8 +84,6 @@
}
mCamera.startPreview();
-
- mTextureView.setCameraDistance(5000);
}
@Override
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 338cb4d..c20c716 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -27,6 +27,7 @@
import android.net.NetworkInfo;
import android.net.LinkProperties;
import android.net.NetworkStateTracker;
+import android.net.wifi.p2p.WifiP2pManager;
import android.os.Handler;
import android.os.Message;
@@ -58,8 +59,8 @@
private BroadcastReceiver mWifiStateReceiver;
private WifiManager mWifiManager;
- public WifiStateTracker() {
- mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
+ public WifiStateTracker(int netType, String networkName) {
+ mNetworkInfo = new NetworkInfo(netType, 0, networkName, "");
mLinkProperties = new LinkProperties();
mLinkCapabilities = new LinkCapabilities();
@@ -87,6 +88,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
+ filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mWifiStateReceiver = new WifiStateReceiver();
mContext.registerReceiver(mWifiStateReceiver, filter);
@@ -104,7 +106,6 @@
/**
* Re-enable connectivity to a network after a {@link #teardown()}.
- * TODO: do away with return value after making MobileDataStateTracker async
*/
public boolean reconnect() {
mTeardownRequested.set(false);
@@ -115,7 +116,6 @@
/**
* Turn the wireless radio off for a network.
* @param turnOn {@code true} to turn the radio on, {@code false}
- * TODO: do away with return value after making MobileDataStateTracker async
*/
public boolean setRadio(boolean turnOn) {
mWifiManager.setWifiEnabled(turnOn);
@@ -205,7 +205,21 @@
private class WifiStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+
+ if (intent.getAction().equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
+ mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
+ WifiP2pManager.EXTRA_NETWORK_INFO);
+ mLinkProperties = intent.getParcelableExtra(
+ WifiP2pManager.EXTRA_LINK_PROPERTIES);
+ if (mLinkProperties == null) {
+ mLinkProperties = new LinkProperties();
+ }
+ mLinkCapabilities = intent.getParcelableExtra(
+ WifiP2pManager.EXTRA_LINK_CAPABILITIES);
+ if (mLinkCapabilities == null) {
+ mLinkCapabilities = new LinkCapabilities();
+ }
+ } else if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
mLinkProperties = intent.getParcelableExtra(
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index ea212ac..cc1f062 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -19,13 +19,17 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.WorkSource;
import android.os.Messenger;
+import android.util.Log;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
@@ -98,6 +102,22 @@
public static final String EXTRA_NETWORK_INFO = "networkInfo";
/**
+ * The lookup key for a {@link android.net.LinkProperties} object associated with the
+ * network. Retrieve with
+ * {@link android.content.Intent#getParcelableExtra(String)}.
+ * @hide
+ */
+ public static final String EXTRA_LINK_PROPERTIES = "linkProperties";
+
+ /**
+ * The lookup key for a {@link android.net.LinkCapabilities} object associated with the
+ * network. Retrieve with
+ * {@link android.content.Intent#getParcelableExtra(String)}.
+ * @hide
+ */
+ public static final String EXTRA_LINK_CAPABILITIES = "linkCapabilities";
+
+ /**
* Broadcast intent action indicating that the available peer list has changed
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -115,9 +135,6 @@
IWifiP2pManager mService;
- /* For communication with WifiP2pService */
- private AsyncChannel mAsyncChannel = new AsyncChannel();
-
/* AsyncChannel notifications to apps */
public static final int HANDLER_CONNECTION = AsyncChannel.CMD_CHANNEL_HALF_CONNECTED;
public static final int HANDLER_DISCONNECTION = AsyncChannel.CMD_CHANNEL_DISCONNECTED;
@@ -194,18 +211,35 @@
}
/**
- * Registers the application handler with the Wi-Fi framework.
- * This function must be the first to be called before any p2p control
- * or query operations can be performed.
+ * A channel that connects the application handler to the Wifi framework.
+ * All p2p operations are performed on a channel.
+ */
+ public class Channel {
+ Channel(AsyncChannel c) {
+ mAsyncChannel = c;
+ }
+ AsyncChannel mAsyncChannel;
+ }
+
+ /**
+ * Registers the application handler with the Wi-Fi framework. This function
+ * must be the first to be called before any p2p control or query operations can be performed.
* @param srcContext is the context of the source
* @param srcHandler is the handler on which the source receives messages
- * @return {@code true} if the operation succeeded
+ * @return Channel instance that is necessary for performing p2p operations
*/
- public boolean connectHandler(Context srcContext, Handler srcHandler) {
+ public Channel initialize(Context srcContext, Handler srcHandler) {
Messenger messenger = getMessenger();
- if (messenger == null) return false;
- return mAsyncChannel.connectSync(srcContext, srcHandler, messenger)
- == AsyncChannel.STATUS_SUCCESSFUL;
+ if (messenger == null) return null;
+
+ AsyncChannel asyncChannel = new AsyncChannel();
+ Channel c = new Channel(asyncChannel);
+ if (asyncChannel.connectSync(srcContext, srcHandler, messenger)
+ == AsyncChannel.STATUS_SUCCESSFUL) {
+ return c;
+ } else {
+ return null;
+ }
}
public boolean isP2pSupported() {
@@ -220,16 +254,18 @@
* Sends in a request to the system to enable p2p. This will pop up a dialog
* to the user and upon authorization will enable p2p.
*/
- public void enableP2p() {
- mAsyncChannel.sendMessage(ENABLE_P2P);
+ public void enableP2p(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(ENABLE_P2P);
}
/**
* Sends in a request to the system to disable p2p. This will pop up a dialog
* to the user and upon authorization will enable p2p.
*/
- public void disableP2p() {
- mAsyncChannel.sendMessage(DISABLE_P2P);
+ public void disableP2p(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(DISABLE_P2P);
}
/**
@@ -238,29 +274,33 @@
* A dialog to the user is thrown to request his permission since it can
* have a significant impact on power consumption
*/
- public void setListenState(int timeout) {
- mAsyncChannel.sendMessage(START_LISTEN_MODE, timeout);
+ public void setListenState(Channel c, int timeout) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(START_LISTEN_MODE, timeout);
}
/**
* Initiates peer discovery
*/
- public void discoverPeers() {
- mAsyncChannel.sendMessage(DISCOVER_PEERS);
+ public void discoverPeers(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(DISCOVER_PEERS);
}
/**
* Initiates peer discovery with a timeout
*/
- public void discoverPeers(int timeout) {
- mAsyncChannel.sendMessage(DISCOVER_PEERS, timeout);
+ public void discoverPeers(Channel c, int timeout) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(DISCOVER_PEERS, timeout);
}
/**
* Cancel any existing peer discovery operation
*/
- public void cancelPeerDiscovery() {
- mAsyncChannel.sendMessage(CANCEL_DISCOVER_PEERS);
+ public void cancelPeerDiscovery(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(CANCEL_DISCOVER_PEERS);
}
/**
@@ -268,47 +308,53 @@
*
* @param peer Configuration described in a {@link WifiP2pConfig} object.
*/
- public void connect(WifiP2pConfig config) {
- mAsyncChannel.sendMessage(CONNECT, config);
+ public void connect(Channel c, WifiP2pConfig config) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(CONNECT, config);
}
/**
* Cancel any ongoing negotiation or disconnect from an existing group
*/
- public void disconnect() {
- mAsyncChannel.sendMessage(CANCEL_CONNECT);
+ public void disconnect(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(CANCEL_CONNECT);
}
/**
* Create a p2p group. This is essentially an access point that can accept
* client connections.
*/
- public void createGroup() {
- mAsyncChannel.sendMessage(CREATE_GROUP);
+ public void createGroup(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(CREATE_GROUP);
}
/**
* Remove the current group. This also removes the p2p interface created
* during group formation.
*/
- public void removeGroup() {
- mAsyncChannel.sendMessage(REMOVE_GROUP);
+ public void removeGroup(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(REMOVE_GROUP);
}
/**
* Request current p2p settings. This returns a RESPONSE_SETTINGS on the source
* handler.
*/
- public void requestP2pSettings() {
- mAsyncChannel.sendMessage(REQUEST_SETTINGS);
+ public void requestP2pSettings(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(REQUEST_SETTINGS);
}
/**
* Request the list of peers. This returns a RESPONSE_PEERS on the source
* handler.
*/
- public void requestPeers() {
- mAsyncChannel.sendMessage(REQUEST_PEERS);
+ public void requestPeers(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(REQUEST_PEERS);
}
/**
@@ -322,8 +368,9 @@
* Request device connection status. This returns a RESPONSE_CONNECTION_STATUS on
* the source handler.
*/
- public void requestConnectionStatus() {
- mAsyncChannel.sendMessage(REQUEST_CONNECTION_STATUS);
+ public void requestConnectionStatus(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_STATUS);
}
@@ -341,4 +388,38 @@
return null;
}
}
+
+
+ /**
+ * Setup DNS connectivity on the current process to the connected Wi-Fi p2p peers
+ *
+ * @return -1 on failure
+ * @hide
+ */
+ public int startPeerCommunication() {
+ IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+ IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
+ try {
+ return cm.startUsingNetworkFeature(ConnectivityManager.TYPE_WIFI, "p2p", new Binder());
+ } catch (RemoteException e) {
+ return -1;
+ }
+ }
+
+ /**
+ * Tear down connectivity to the connected Wi-Fi p2p peers
+ *
+ * @return -1 on failure
+ * @hide
+ */
+ public int stopPeerCommunication() {
+ IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+ IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
+ try {
+ return cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_WIFI, "p2p");
+ } catch (RemoteException e) {
+ return -1;
+ }
+ }
+
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 3678cfc..176191e 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -25,6 +25,15 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.net.IConnectivityManager;
+import android.net.ConnectivityManager;
+import android.net.DhcpInfoInternal;
+import android.net.DhcpStateMachine;
+import android.net.InterfaceConfiguration;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.NetworkUtils;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiMonitor;
import android.net.wifi.WifiNative;
@@ -47,16 +56,16 @@
import android.view.WindowManager;
import android.widget.EditText;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.Collection;
-
import com.android.internal.R;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Collection;
+
/**
* WifiP2pService inclues a state machine to perform Wi-Fi p2p operations. Applications
* communicate with this service to issue device discovery and connectivity requests
@@ -70,14 +79,16 @@
public class WifiP2pService extends IWifiP2pManager.Stub {
private static final String TAG = "WifiP2pService";
private static final boolean DBG = true;
+ private static final String NETWORKTYPE = "WIFI_P2P";
private Context mContext;
private String mInterface;
INetworkManagementService mNwService;
+ private DhcpStateMachine mDhcpStateMachine;
- // Tracked to notify the user about wifi client/hotspot being shut down
- // during p2p bring up
+ //Tracked to notify the user about wifi client/hotspot being shut down
+ //during p2p bring up
private int mWifiState = WifiManager.WIFI_STATE_DISABLED;
private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
@@ -85,6 +96,9 @@
private AsyncChannel mReplyChannel = new AsyncChannel();;
private AsyncChannel mWifiChannel;
+ private static final int GROUP_NEGOTIATION_WAIT_TIME_MS = 60 * 1000;
+ private static int mGroupNegotiationTimeoutIndex = 0;
+
private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
/* Message sent to WifiStateMachine to indicate p2p enable is pending */
@@ -92,15 +106,24 @@
/* Message sent to WifiStateMachine to indicate Wi-Fi client/hotspot operation can proceed */
public static final int WIFI_ENABLE_PROCEED = BASE + 2;
+ /* Delayed message to timeout of group negotiation */
+ public static final int GROUP_NEGOTIATION_TIMED_OUT = BASE + 3;
+
/* User accepted to disable Wi-Fi in order to enable p2p */
private static final int WIFI_DISABLE_USER_ACCEPT = BASE + 11;
private final boolean mP2pSupported;
+ private NetworkInfo mNetworkInfo;
+ private LinkProperties mLinkProperties;
+
public WifiP2pService(Context context) {
mContext = context;
mInterface = SystemProperties.get("wifi.interface", "wlan0");
+ mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
+ mLinkProperties = new LinkProperties();
+
mP2pSupported = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_wifi_p2p_support);
@@ -113,7 +136,7 @@
filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
mContext.registerReceiver(new WifiStateReceiver(), filter);
- }
+ }
public void connectivityServiceReady() {
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
@@ -300,6 +323,7 @@
break;
// Ignore
case WIFI_DISABLE_USER_ACCEPT:
+ case GROUP_NEGOTIATION_TIMED_OUT:
break;
default:
Slog.e(TAG, "Unhandled message " + message);
@@ -459,6 +483,10 @@
WifiP2pManager.ENABLE_P2P_SUCCEEDED);
transitionTo(mInactiveState);
break;
+ case WifiP2pManager.DISABLE_P2P:
+ //TODO: fix
+ WifiNative.killSupplicant();
+ transitionTo(mP2pDisabledState);
default:
return NOT_HANDLED;
}
@@ -471,6 +499,7 @@
public void enter() {
if (DBG) Slog.d(TAG, getName());
sendP2pStateChangedBroadcast(true);
+ mNetworkInfo.setIsAvailable(true);
}
@Override
@@ -526,6 +555,7 @@
@Override
public void exit() {
sendP2pStateChangedBroadcast(false);
+ mNetworkInfo.setIsAvailable(false);
}
}
@@ -550,6 +580,8 @@
WifiP2pGroup group = (WifiP2pGroup) message.obj;
notifyP2pInvitationReceived(group);
break;
+ case WifiP2pManager.REQUEST_PEERS:
+ return NOT_HANDLED;
default:
return NOT_HANDLED;
}
@@ -558,8 +590,11 @@
}
class GroupNegotiationState extends State {
- @Override public void enter() {
+ @Override
+ public void enter() {
if (DBG) Slog.d(TAG, getName());
+ sendMessageDelayed(obtainMessage(GROUP_NEGOTIATION_TIMED_OUT,
+ ++mGroupNegotiationTimeoutIndex, 0), GROUP_NEGOTIATION_WAIT_TIME_MS);
}
@Override
@@ -582,18 +617,29 @@
case WifiMonitor.P2P_GROUP_STARTED_EVENT:
mGroup = (WifiP2pGroup) message.obj;
if (DBG) Slog.d(TAG, getName() + " group started");
- // If this device is GO, do nothing since there is a follow up
- // AP_STA_CONNECTED event
- if (!mGroup.isGroupOwner()) {
+ if (mGroup.isGroupOwner()) {
+ startDhcpServer(mGroup.getInterface());
+ } else {
+ mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
+ P2pStateMachine.this, mGroup.getInterface());
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
WifiP2pDevice groupOwner = mGroup.getOwner();
updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
sendP2pPeersChangedBroadcast();
}
transitionTo(mGroupCreatedState);
break;
- case WifiP2pManager.CANCEL_CONNECT:
+ case WifiP2pManager.CANCEL_CONNECT:
// TODO: fix
break;
+ case GROUP_NEGOTIATION_TIMED_OUT:
+ if (mGroupNegotiationTimeoutIndex == message.arg1) {
+ if (DBG) Slog.d(TAG, "Group negotiation timed out");
+ updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
+ mSavedConnectConfig = null;
+ transitionTo(mInactiveState);
+ }
+ break;
default:
return NOT_HANDLED;
}
@@ -605,6 +651,11 @@
@Override
public void enter() {
if (DBG) Slog.d(TAG, getName());
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+
+ if (mGroup.isGroupOwner()) {
+ sendP2pConnectionChangedBroadcast();
+ }
}
@Override
@@ -638,7 +689,16 @@
}
if (DBG) Slog.e(TAG, getName() + " ap sta disconnected");
break;
- // Disconnect & remove group have same effect when connected
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
+ if (DBG) Slog.d(TAG, "DhcpInfo: " + dhcpInfo);
+ if (dhcpInfo != null) {
+ mLinkProperties = dhcpInfo.makeLinkProperties();
+ mLinkProperties.setInterfaceName(mGroup.getInterface());
+ sendP2pConnectionChangedBroadcast();
+ }
+ break;
+ //disconnect & remove group have same effect when connected
case WifiP2pManager.CANCEL_CONNECT:
case WifiP2pManager.REMOVE_GROUP:
if (DBG) Slog.e(TAG, getName() + " remove group");
@@ -655,6 +715,16 @@
changed = true;
}
}
+
+ if (mGroup.isGroupOwner()) {
+ stopDhcpServer();
+ } else {
+ if (DBG) Slog.d(TAG, "stop DHCP client");
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
+ mDhcpStateMachine.quit();
+ mDhcpStateMachine = null;
+ }
+
mGroup = null;
if (changed) sendP2pPeersChangedBroadcast();
transitionTo(mInactiveState);
@@ -663,10 +733,12 @@
WifiP2pDevice device = (WifiP2pDevice) message.obj;
if (device.equals(mGroup.getOwner())) {
Slog.d(TAG, "Lost the group owner, killing p2p connection");
- sendMessage(WifiP2pManager.REMOVE_GROUP);
+ WifiNative.p2pFlush();
+ WifiNative.p2pGroupRemove(mGroup.getInterface());
} else if (mGroup.removeClient(device) && mGroup.isClientListEmpty()) {
Slog.d(TAG, "Client list empty, killing p2p connection");
- sendMessage(WifiP2pManager.REMOVE_GROUP);
+ WifiNative.p2pFlush();
+ WifiNative.p2pGroupRemove(mGroup.getInterface());
}
return NOT_HANDLED; // Do the regular device lost handling
case WifiP2pManager.DISABLE_P2P:
@@ -705,6 +777,10 @@
}
return HANDLED;
}
+
+ public void exit() {
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+ }
}
private void sendP2pStateChangedBroadcast(boolean enabled) {
@@ -726,6 +802,55 @@
mContext.sendBroadcast(intent);
}
+ private void sendP2pConnectionChangedBroadcast() {
+ if (DBG) Slog.d(TAG, "sending p2p connection changed broadcast");
+ Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+ | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
+ intent.putExtra(WifiP2pManager.EXTRA_LINK_PROPERTIES,
+ new LinkProperties (mLinkProperties));
+ mContext.sendStickyBroadcast(intent);
+ }
+
+ private void startDhcpServer(String intf) {
+ /* Is chosen as a unique range to avoid conflict with
+ the range defined in Tethering.java */
+ String[] dhcp_range = {"192.168.49.2", "192.168.49.254"};
+ String serverAddress = "192.168.49.1";
+
+ mLinkProperties.clear();
+ mLinkProperties.setInterfaceName(mGroup.getInterface());
+
+ InterfaceConfiguration ifcg = null;
+ try {
+ ifcg = mNwService.getInterfaceConfig(intf);
+ ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress(
+ serverAddress), 24);
+ ifcg.interfaceFlags = "[up]";
+ mNwService.setInterfaceConfig(intf, ifcg);
+ /* This starts the dnsmasq server */
+ mNwService.startTethering(dhcp_range);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error configuring interface " + intf + ", :" + e);
+ return;
+ }
+
+ mLinkProperties.addDns(NetworkUtils.numericToInetAddress(serverAddress));
+ Slog.d(TAG, "Started Dhcp server on " + intf);
+ }
+
+ private void stopDhcpServer() {
+ try {
+ mNwService.stopTethering();
+ } catch (Exception e) {
+ Slog.e(TAG, "Error stopping Dhcp server" + e);
+ return;
+ }
+
+ Slog.d(TAG, "Stopped Dhcp server");
+ }
+
private void notifyP2pEnableFailure() {
Resources r = Resources.getSystem();
AlertDialog dialog = new AlertDialog.Builder(mContext)
@@ -760,11 +885,16 @@
.setView(textEntryView)
.setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText());
+ if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText());
+
+ if (pin.getVisibility() == View.GONE) {
+ mSavedGoNegotiationConfig.wpsConfig.setup = Setup.PBC;
+ } else {
mSavedGoNegotiationConfig.wpsConfig.setup = Setup.KEYPAD;
mSavedGoNegotiationConfig.wpsConfig.pin = pin.getText().toString();
- sendMessage(WifiP2pManager.CONNECT, mSavedGoNegotiationConfig);
- mSavedGoNegotiationConfig = null;
+ }
+ sendMessage(WifiP2pManager.CONNECT, mSavedGoNegotiationConfig);
+ mSavedGoNegotiationConfig = null;
}
})
.setNegativeButton(r.getString(R.string.cancel), new OnClickListener() {