Merge "Fix issue #4554429: API REVIEW: deprecate Live Folders"
diff --git a/api/current.txt b/api/current.txt
index 084f16a..f380cf9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -709,6 +709,7 @@
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
+ field public static final int overridesImplicitlyEnabledSubtype = 16843696; // 0x10103b0
field public static final int packageNames = 16843649; // 0x1010381
field public static final int padding = 16842965; // 0x10100d5
field public static final int paddingBottom = 16842969; // 0x10100d9
@@ -10668,7 +10669,7 @@
method public void setAuxEffectSendLevel(float);
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
- method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+ method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDisplay(android.view.SurfaceHolder);
@@ -18463,7 +18464,7 @@
field public static final java.lang.String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService";
}
- public abstract class SpellCheckerService.Session {
+ public static abstract class SpellCheckerService.Session {
ctor public SpellCheckerService.Session();
method public android.os.Bundle getBundle();
method public java.lang.String getLocale();
@@ -24486,7 +24487,7 @@
method public boolean isWatchingCursor(android.view.View);
method public void restartInput(android.view.View);
method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle);
- method public boolean setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
+ method public void setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
method public boolean setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype);
method public void setInputMethod(android.os.IBinder, java.lang.String);
method public void setInputMethodAndSubtype(android.os.IBinder, java.lang.String, android.view.inputmethod.InputMethodSubtype);
@@ -24531,8 +24532,7 @@
}
public final class InputMethodSubtype implements android.os.Parcelable {
- ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String);
- ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean);
+ ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean);
method public boolean containsExtraValueKey(java.lang.String);
method public int describeContents();
method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
@@ -24543,6 +24543,7 @@
method public java.lang.String getMode();
method public int getNameResId();
method public boolean isAuxiliary();
+ method public boolean overridesImplicitlyEnabledSubtype();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index aa3bc03..b13236a 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -357,9 +357,9 @@
}
sp<IMediaPlayer> player =
- service->create(getpid(), client, source, 0);
+ service->create(getpid(), client, 0);
- if (player != NULL) {
+ if (player != NULL && player->setDataSource(source) == NO_ERROR) {
player->setVideoSurface(surface);
player->start();
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index e5f3273..3918cfd 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -320,15 +320,36 @@
* checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
*/
public long getTotalBytes() {
- long totalBytes = 0;
+ final Entry entry = getTotal(null);
+ return entry.rxBytes + entry.txBytes;
+ }
+
+ /**
+ * Return total of all fields represented by this snapshot object.
+ */
+ public Entry getTotal(Entry recycle) {
+ final Entry entry = recycle != null ? recycle : new Entry();
+
+ entry.iface = IFACE_ALL;
+ entry.uid = UID_ALL;
+ entry.set = SET_ALL;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = 0;
+ entry.rxPackets = 0;
+ entry.txBytes = 0;
+ entry.txPackets = 0;
+
for (int i = 0; i < size; i++) {
// skip specific tags, since already counted in TAG_NONE
if (tag[i] != TAG_NONE) continue;
- totalBytes += rxBytes[i];
- totalBytes += txBytes[i];
+ entry.rxBytes += rxBytes[i];
+ entry.rxPackets += rxPackets[i];
+ entry.txBytes += txBytes[i];
+ entry.txPackets += txPackets[i];
+ entry.operations += operations[i];
}
- return totalBytes;
+ return entry;
}
/**
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index 3e2e38e..b96099e 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -66,7 +66,7 @@
/**
* This abstract class should be overridden by a concrete implementation of a spell checker.
*/
- public abstract class Session {
+ public static abstract class Session {
private InternalISpellCheckerSession mInternalSession;
/**
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 4ec4ff9..0119d03 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -164,7 +164,9 @@
a.getString(com.android.internal.R.styleable
.InputMethod_Subtype_imeSubtypeExtraValue),
a.getBoolean(com.android.internal.R.styleable
- .InputMethod_Subtype_isAuxiliary, false));
+ .InputMethod_Subtype_isAuxiliary, false),
+ a.getBoolean(com.android.internal.R.styleable
+ .InputMethod_Subtype_overridesImplicitlyEnabledSubtype, false));
mSubtypes.add(subtype);
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 302be57..3ead9df 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1593,15 +1593,13 @@
* to the current implementation.)
* @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
* @param subtypes subtypes will be added as additional subtypes of the current input method.
- * @return true if the additional input method subtypes are successfully added.
*/
- public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
+ public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
synchronized (mH) {
try {
- return mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
+ mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
- return false;
}
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 4a98336..5670432 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -42,6 +42,7 @@
private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
private final boolean mIsAuxiliary;
+ private final boolean mOverridesImplicitlyEnabledSubtype;
private final int mSubtypeHashCode;
private final int mSubtypeIconResId;
private final int mSubtypeNameResId;
@@ -57,10 +58,12 @@
* @param locale The locale supported by the subtype
* @param mode The mode supported by the subtype
* @param extraValue The extra value of the subtype
+ * @param isAuxiliary true when this subtype is one shot subtype.
+ * @hide
*/
- public InputMethodSubtype(
- int nameId, int iconId, String locale, String mode, String extraValue) {
- this(nameId, iconId, locale, mode, extraValue, false);
+ public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
+ boolean isAuxiliary) {
+ this(nameId, iconId, locale, mode, extraValue, false, false);
}
/**
@@ -71,17 +74,21 @@
* @param mode The mode supported by the subtype
* @param extraValue The extra value of the subtype
* @param isAuxiliary true when this subtype is one shot subtype.
+ * @param overridesImplicitlyEnabledSubtype true when this subtype should be selected by default
+ * if no other subtypes are selected explicitly. Note that a subtype with this parameter being
+ * true will not be shown in the subtypes list.
*/
public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
- boolean isAuxiliary) {
+ boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
mSubtypeNameResId = nameId;
mSubtypeIconResId = iconId;
mSubtypeLocale = locale != null ? locale : "";
mSubtypeMode = mode != null ? mode : "";
mSubtypeExtraValue = extraValue != null ? extraValue : "";
mIsAuxiliary = isAuxiliary;
+ mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype;
mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
- mIsAuxiliary);
+ mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
}
InputMethodSubtype(Parcel source) {
@@ -95,8 +102,9 @@
s = source.readString();
mSubtypeExtraValue = s != null ? s : "";
mIsAuxiliary = (source.readInt() == 1);
+ mOverridesImplicitlyEnabledSubtype = (source.readInt() == 1);
mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
- mIsAuxiliary);
+ mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
}
/**
@@ -144,6 +152,14 @@
}
/**
+ * @return true when this subtype is selected by default if no other subtypes are selected
+ * explicitly. Note that a subtype that returns true will not be shown in the subtypes list.
+ */
+ public boolean overridesImplicitlyEnabledSubtype() {
+ return mOverridesImplicitlyEnabledSubtype;
+ }
+
+ /**
* @param context Context will be used for getting Locale and PackageManager.
* @param packageName The package name of the IME
* @param appInfo The application info of the IME
@@ -242,6 +258,7 @@
dest.writeString(mSubtypeMode);
dest.writeString(mSubtypeExtraValue);
dest.writeInt(mIsAuxiliary ? 1 : 0);
+ dest.writeInt(mOverridesImplicitlyEnabledSubtype ? 1 : 0);
}
public static final Parcelable.Creator<InputMethodSubtype> CREATOR
@@ -274,8 +291,9 @@
}
private static int hashCodeInternal(String locale, String mode, String extraValue,
- boolean isAuxiliary) {
- return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary});
+ boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
+ return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary,
+ overridesImplicitlyEnabledSubtype});
}
/**
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 73a30c4..c895b84 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -538,6 +538,8 @@
private native void nativeSendListBoxChoice(int choice);
+ private native void nativeCloseIdleConnections();
+
/* Tell webkit what its width and height are, for the purposes
of layout/line-breaking. These coordinates are in document space,
which is the same as View coords unless we have zoomed the document
@@ -1262,6 +1264,8 @@
if (!JniUtil.useChromiumHttpStack()) {
WebViewWorker.getHandler().sendEmptyMessage(
WebViewWorker.MSG_PAUSE_CACHE_TRANSACTION);
+ } else {
+ nativeCloseIdleConnections();
}
break;
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index ce0299c..683aca5 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -68,5 +68,5 @@
boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype);
boolean switchToLastInputMethod(in IBinder token);
boolean setInputMethodEnabled(String id, boolean enabled);
- boolean setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
+ oneway void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
}
diff --git a/core/res/res/layout-sw600dp/status_bar_latest_event_ticker.xml b/core/res/res/layout-sw600dp/status_bar_latest_event_ticker.xml
index 7631781..269e086 100644
--- a/core/res/res/layout-sw600dp/status_bar_latest_event_ticker.xml
+++ b/core/res/res/layout-sw600dp/status_bar_latest_event_ticker.xml
@@ -38,8 +38,8 @@
android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_marginTop="-10dp"
+ android:layout_marginBottom="6dip"
+ android:gravity="bottom"
android:singleLine="true"
/>
</LinearLayout>
-
diff --git a/core/res/res/layout-sw600dp/status_bar_latest_event_ticker_large_icon.xml b/core/res/res/layout-sw600dp/status_bar_latest_event_ticker_large_icon.xml
index ff0f7d4..69eac92 100644
--- a/core/res/res/layout-sw600dp/status_bar_latest_event_ticker_large_icon.xml
+++ b/core/res/res/layout-sw600dp/status_bar_latest_event_ticker_large_icon.xml
@@ -33,8 +33,9 @@
android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:layout_marginBottom="6dip"
+ android:gravity="bottom"
android:singleLine="true"
- android:layout_marginTop="-10dp"
/>
<ImageView android:id="@+id/icon"
android:layout_width="wrap_content"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b50c063..0bf5b0a 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2237,6 +2237,10 @@
InputMethodManager#switchToLastInputMethod will ignore auxiliary subtypes when it
chooses a target subtype. -->
<attr name="isAuxiliary" format="boolean" />
+ <!-- Set true when this subtype should be selected by default if no other subtypes are
+ selected explicitly. Note that a subtype with this parameter being true will
+ not be shown in the subtypes list. -->
+ <attr name="overridesImplicitlyEnabledSubtype" format="boolean" />
<!-- The extra value of the subtype. This string can be any string and will be passed to
the IME when the framework calls the IME with the subtype. -->
<attr name="imeSubtypeExtraValue" format="string" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6988f6b..bc2b907 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2010,4 +2010,5 @@
<public type="attr" name="targetDescriptions" />
<public type="attr" name="directionDescriptions" />
+ <public type="attr" name="overridesImplicitlyEnabledSubtype" />
</resources>
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index d552b2e..0e2cdf7 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -20,11 +20,13 @@
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
+#include <utils/KeyedVector.h>
namespace android {
class Parcel;
class Surface;
+class IStreamSource;
class ISurfaceTexture;
class IMediaPlayer: public IInterface
@@ -34,6 +36,10 @@
virtual void disconnect() = 0;
+ virtual status_t setDataSource(const char *url,
+ const KeyedVector<String8, String8>* headers) = 0;
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
+ virtual status_t setDataSource(const sp<IStreamSource>& source) = 0;
virtual status_t setVideoSurface(const sp<Surface>& surface) = 0;
virtual status_t setVideoSurfaceTexture(
const sp<ISurfaceTexture>& surfaceTexture) = 0;
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 7956788..93bbe13 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -39,17 +39,9 @@
public:
DECLARE_META_INTERFACE(MediaPlayerService);
- virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
+ virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
- const char* url, const KeyedVector<String8, String8> *headers = NULL,
- int audioSessionId = 0) = 0;
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
- int fd, int64_t offset, int64_t length, int audioSessionId) = 0;
-
- virtual sp<IMediaPlayer> create(
- pid_t pid, const sp<IMediaPlayerClient> &client,
- const sp<IStreamSource> &source, int audioSessionId) = 0;
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 1a67671..e98d55c 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -21,6 +21,7 @@
#include <media/IMediaPlayerClient.h>
#include <media/IMediaPlayer.h>
#include <media/IMediaDeathNotifier.h>
+#include <media/IStreamSource.h>
#include <utils/KeyedVector.h>
#include <utils/String8.h>
@@ -168,6 +169,7 @@
const KeyedVector<String8, String8> *headers);
status_t setDataSource(int fd, int64_t offset, int64_t length);
+ status_t setDataSource(const sp<IStreamSource> &source);
status_t setVideoSurface(const sp<Surface>& surface);
status_t setVideoSurfaceTexture(
const sp<ISurfaceTexture>& surfaceTexture);
@@ -206,7 +208,7 @@
status_t seekTo_l(int msec);
status_t prepareAsync_l();
status_t getDuration_l(int *msec);
- status_t setDataSource(const sp<IMediaPlayer>& player);
+ status_t attachNewPlayer(const sp<IMediaPlayer>& player);
void disconnectNativeWindow();
status_t reset_l();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 1ee9a1f..e25f654 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -459,6 +459,9 @@
* android.R.styleable#AndroidManifestUsesPermission <uses-permission>}
* element.
*
+ * <p>This class requires the {@link android.Manifest.permission#INTERNET} permission
+ * when used with network-based content.
+ *
* <a name="Callbacks"></a>
* <h3>Callbacks</h3>
* <p>Applications may want to register for informational and error
@@ -828,6 +831,7 @@
fd.close();
}
}
+
Log.d(TAG, "Couldn't open file on client side, trying server side");
setDataSource(uri.toString(), headers);
return;
@@ -839,7 +843,8 @@
* @param path the path of the file, or the http/rtsp URL of the stream you want to play
* @throws IllegalStateException if it is called in an invalid state
*/
- public native void setDataSource(String path) throws IOException, IllegalArgumentException, IllegalStateException;
+ public native void setDataSource(String path)
+ throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
/**
* Sets the data source (file-path or http/rtsp URL) to use.
@@ -850,7 +855,7 @@
* @hide pending API council
*/
public void setDataSource(String path, Map<String, String> headers)
- throws IOException, IllegalArgumentException, IllegalStateException
+ throws IOException, IllegalArgumentException, SecurityException, IllegalStateException
{
String[] keys = null;
String[] values = null;
@@ -871,7 +876,7 @@
private native void _setDataSource(
String path, String[] keys, String[] values)
- throws IOException, IllegalArgumentException, IllegalStateException;
+ throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
/**
* Sets the data source (FileDescriptor) to use. It is the caller's responsibility
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 354f2c9..5dfbe01 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -155,6 +155,8 @@
} else { // Throw exception!
if ( opStatus == (status_t) INVALID_OPERATION ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
+ jniThrowException(env, "java/lang/SecurityException", NULL);
} else if ( opStatus != (status_t) OK ) {
if (strlen(message) > 230) {
// if the message is too long, don't bother displaying the status code
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 52885d2..bd89ad8 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -21,14 +21,20 @@
#include <binder/Parcel.h>
#include <media/IMediaPlayer.h>
+#include <media/IStreamSource.h>
+
#include <surfaceflinger/ISurface.h>
#include <surfaceflinger/Surface.h>
#include <gui/ISurfaceTexture.h>
+#include <utils/String8.h>
namespace android {
enum {
DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+ SET_DATA_SOURCE_URL,
+ SET_DATA_SOURCE_FD,
+ SET_DATA_SOURCE_STREAM,
SET_VIDEO_SURFACE,
PREPARE_ASYNC,
START,
@@ -68,6 +74,43 @@
remote()->transact(DISCONNECT, data, &reply);
}
+ status_t setDataSource(const char* url,
+ const KeyedVector<String8, String8>* headers)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeCString(url);
+ if (headers == NULL) {
+ data.writeInt32(0);
+ } else {
+ // serialize the headers
+ data.writeInt32(headers->size());
+ for (size_t i = 0; i < headers->size(); ++i) {
+ data.writeString8(headers->keyAt(i));
+ data.writeString8(headers->valueAt(i));
+ }
+ }
+ remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setDataSource(int fd, int64_t offset, int64_t length) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeFileDescriptor(fd);
+ data.writeInt64(offset);
+ data.writeInt64(length);
+ remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setDataSource(const sp<IStreamSource> &source) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeStrongBinder(source->asBinder());
+ return reply.readInt32();
+ }
+
// pass the buffered Surface to the media player service
status_t setVideoSurface(const sp<Surface>& surface)
{
@@ -273,6 +316,34 @@
disconnect();
return NO_ERROR;
} break;
+ case SET_DATA_SOURCE_URL: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ const char* url = data.readCString();
+ KeyedVector<String8, String8> headers;
+ int32_t numHeaders = data.readInt32();
+ for (int i = 0; i < numHeaders; ++i) {
+ String8 key = data.readString8();
+ String8 value = data.readString8();
+ headers.add(key, value);
+ }
+ reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
+ return NO_ERROR;
+ } break;
+ case SET_DATA_SOURCE_FD: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ int fd = data.readFileDescriptor();
+ int64_t offset = data.readInt64();
+ int64_t length = data.readInt64();
+ reply->writeInt32(setDataSource(fd, offset, length));
+ return NO_ERROR;
+ }
+ case SET_DATA_SOURCE_STREAM: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ sp<IStreamSource> source =
+ interface_cast<IStreamSource>(data.readStrongBinder());
+ reply->writeInt32(setDataSource(source));
+ return NO_ERROR;
+ }
case SET_VIDEO_SURFACE: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<Surface> surface = Surface::readFromParcel(data);
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 17a0362..8e4dd04 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -30,9 +30,7 @@
namespace android {
enum {
- CREATE_URL = IBinder::FIRST_CALL_TRANSACTION,
- CREATE_FD,
- CREATE_STREAM,
+ CREATE = IBinder::FIRST_CALL_TRANSACTION,
DECODE_URL,
DECODE_FD,
CREATE_MEDIA_RECORDER,
@@ -60,28 +58,14 @@
}
virtual sp<IMediaPlayer> create(
- pid_t pid, const sp<IMediaPlayerClient>& client,
- const char* url, const KeyedVector<String8, String8> *headers, int audioSessionId) {
+ pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(pid);
data.writeStrongBinder(client->asBinder());
- data.writeCString(url);
-
- if (headers == NULL) {
- data.writeInt32(0);
- } else {
- // serialize the headers
- data.writeInt32(headers->size());
- for (size_t i = 0; i < headers->size(); ++i) {
- data.writeString8(headers->keyAt(i));
- data.writeString8(headers->valueAt(i));
- }
- }
data.writeInt32(audioSessionId);
- remote()->transact(CREATE_URL, data, &reply);
-
+ remote()->transact(CREATE, data, &reply);
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
}
@@ -94,38 +78,6 @@
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
}
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd,
- int64_t offset, int64_t length, int audioSessionId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
- data.writeInt32(pid);
- data.writeStrongBinder(client->asBinder());
- data.writeFileDescriptor(fd);
- data.writeInt64(offset);
- data.writeInt64(length);
- data.writeInt32(audioSessionId);
-
- remote()->transact(CREATE_FD, data, &reply);
-
- return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
- }
-
- virtual sp<IMediaPlayer> create(
- pid_t pid, const sp<IMediaPlayerClient> &client,
- const sp<IStreamSource> &source, int audioSessionId) {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
- data.writeInt32(static_cast<int32_t>(pid));
- data.writeStrongBinder(client->asBinder());
- data.writeStrongBinder(source->asBinder());
- data.writeInt32(static_cast<int32_t>(audioSessionId));
-
- remote()->transact(CREATE_STREAM, data, &reply);
-
- return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
- }
-
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
{
Parcel data, reply;
@@ -181,62 +133,16 @@
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
- case CREATE_URL: {
+ case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
pid_t pid = data.readInt32();
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
- const char* url = data.readCString();
-
- KeyedVector<String8, String8> headers;
- int32_t numHeaders = data.readInt32();
- for (int i = 0; i < numHeaders; ++i) {
- String8 key = data.readString8();
- String8 value = data.readString8();
- headers.add(key, value);
- }
int audioSessionId = data.readInt32();
-
- sp<IMediaPlayer> player = create(
- pid, client, url, numHeaders > 0 ? &headers : NULL, audioSessionId);
-
+ sp<IMediaPlayer> player = create(pid, client, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
- case CREATE_FD: {
- CHECK_INTERFACE(IMediaPlayerService, data, reply);
- pid_t pid = data.readInt32();
- sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder());
- int fd = dup(data.readFileDescriptor());
- int64_t offset = data.readInt64();
- int64_t length = data.readInt64();
- int audioSessionId = data.readInt32();
-
- sp<IMediaPlayer> player = create(pid, client, fd, offset, length, audioSessionId);
- reply->writeStrongBinder(player->asBinder());
- return NO_ERROR;
- } break;
- case CREATE_STREAM:
- {
- CHECK_INTERFACE(IMediaPlayerService, data, reply);
-
- pid_t pid = static_cast<pid_t>(data.readInt32());
-
- sp<IMediaPlayerClient> client =
- interface_cast<IMediaPlayerClient>(data.readStrongBinder());
-
- sp<IStreamSource> source =
- interface_cast<IStreamSource>(data.readStrongBinder());
-
- int audioSessionId = static_cast<int>(data.readInt32());
-
- sp<IMediaPlayer> player =
- create(pid, client, source, audioSessionId);
-
- reply->writeStrongBinder(player->asBinder());
- return OK;
- break;
- }
case DECODE_URL: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
const char* url = data.readCString();
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 67a66a2..0fc6a8a 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -108,7 +108,7 @@
}
-status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player)
+status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
{
status_t err = UNKNOWN_ERROR;
sp<IMediaPlayer> p;
@@ -117,7 +117,7 @@
if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
(mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
- LOGE("setDataSource called in state %d", mCurrentState);
+ LOGE("attachNewPlayer called in state %d", mCurrentState);
return INVALID_OPERATION;
}
@@ -147,9 +147,11 @@
if (url != NULL) {
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
- sp<IMediaPlayer> player(
- service->create(getpid(), this, url, headers, mAudioSessionId));
- err = setDataSource(player);
+ sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+ err = attachNewPlayer(player);
+ if (err == NO_ERROR) {
+ err = mPlayer->setDataSource(url, headers);
+ }
}
}
return err;
@@ -161,8 +163,26 @@
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
- sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));
- err = setDataSource(player);
+ sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+ err = attachNewPlayer(player);
+ if (err == NO_ERROR) {
+ err = mPlayer->setDataSource(fd, offset, length);
+ }
+ }
+ return err;
+}
+
+status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
+{
+ LOGV("setDataSource");
+ status_t err = UNKNOWN_ERROR;
+ const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ if (service != 0) {
+ sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+ err = attachNewPlayer(player);
+ if (err == NO_ERROR) {
+ err = mPlayer->setDataSource(source);
+ }
}
return err;
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 2051b3b..0386d4b 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -176,6 +176,16 @@
namespace android {
+static bool checkPermission(const char* permissionString) {
+#ifndef HAVE_ANDROID_OS
+ return true;
+#endif
+ if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+ bool ok = checkCallingPermission(String16(permissionString));
+ if (!ok) LOGE("Request requires %s", permissionString);
+ return ok;
+}
+
// TODO: Temp hack until we can register players
typedef struct {
const char *extension;
@@ -245,31 +255,8 @@
return retriever;
}
-sp<IMediaPlayer> MediaPlayerService::create(
- pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
- const KeyedVector<String8, String8> *headers, int audioSessionId)
-{
- int32_t connId = android_atomic_inc(&mNextConnId);
-
- sp<Client> c = new Client(
- this, pid, connId, client, audioSessionId,
- IPCThreadState::self()->getCallingUid());
-
- LOGV("Create new client(%d) from pid %d, uid %d, url=%s, connId=%d, audioSessionId=%d",
- connId, pid, IPCThreadState::self()->getCallingUid(), url, connId, audioSessionId);
- if (NO_ERROR != c->setDataSource(url, headers))
- {
- c.clear();
- return c;
- }
- wp<Client> w = c;
- Mutex::Autolock lock(mLock);
- mClients.add(w);
- return c;
-}
-
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
- int fd, int64_t offset, int64_t length, int audioSessionId)
+ int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
@@ -277,40 +264,14 @@
this, pid, connId, client, audioSessionId,
IPCThreadState::self()->getCallingUid());
- LOGV("Create new client(%d) from pid %d, uid %d, fd=%d, offset=%lld, "
- "length=%lld, audioSessionId=%d", connId, pid,
- IPCThreadState::self()->getCallingUid(), fd, offset, length, audioSessionId);
- if (NO_ERROR != c->setDataSource(fd, offset, length)) {
- c.clear();
- } else {
- wp<Client> w = c;
+ LOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
+ IPCThreadState::self()->getCallingUid());
+
+ wp<Client> w = c;
+ {
Mutex::Autolock lock(mLock);
mClients.add(w);
}
- ::close(fd);
- return c;
-}
-
-sp<IMediaPlayer> MediaPlayerService::create(
- pid_t pid, const sp<IMediaPlayerClient> &client,
- const sp<IStreamSource> &source, int audioSessionId) {
- int32_t connId = android_atomic_inc(&mNextConnId);
-
- sp<Client> c = new Client(
- this, pid, connId, client, audioSessionId,
- IPCThreadState::self()->getCallingUid());
-
- LOGV("Create new client(%d) from pid %d, audioSessionId=%d",
- connId, pid, audioSessionId);
-
- if (OK != c->setDataSource(source)) {
- c.clear();
- } else {
- wp<Client> w = c;
- Mutex::Autolock lock(mLock);
- mClients.add(w);
- }
-
return c;
}
@@ -701,6 +662,14 @@
if (url == NULL)
return UNKNOWN_ERROR;
+ if ((strncmp(url, "http://", 7) == 0) ||
+ (strncmp(url, "https://", 8) == 0) ||
+ (strncmp(url, "rtsp://", 7) == 0)) {
+ if (!checkPermission("android.permission.INTERNET")) {
+ return PERMISSION_DENIED;
+ }
+ }
+
if (strncmp(url, "content://", 10) == 0) {
// get a filedescriptor for the content Uri and
// pass it to the setDataSource(fd) method
@@ -781,6 +750,7 @@
// now set data source
mStatus = p->setDataSource(fd, offset, length);
if (mStatus == NO_ERROR) mPlayer = p;
+
return mStatus;
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index e32b92a..53e625a 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -188,16 +188,7 @@
void removeMediaRecorderClient(wp<MediaRecorderClient> client);
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
- // House keeping for media player clients
- virtual sp<IMediaPlayer> create(
- pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
- const KeyedVector<String8, String8> *headers, int audioSessionId);
-
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId);
-
- virtual sp<IMediaPlayer> create(
- pid_t pid, const sp<IMediaPlayerClient> &client,
- const sp<IStreamSource> &source, int audioSessionId);
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId);
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
@@ -284,13 +275,13 @@
sp<MediaPlayerBase> createPlayer(player_type playerType);
- status_t setDataSource(
+ virtual status_t setDataSource(
const char *url,
const KeyedVector<String8, String8> *headers);
- status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- status_t setDataSource(const sp<IStreamSource> &source);
+ virtual status_t setDataSource(const sp<IStreamSource> &source);
static void notify(void* cookie, int msg,
int ext1, int ext2, const Parcel *obj);
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index f2f3500..0794f57 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -110,6 +110,8 @@
}
status_t FileSource::getSize(off64_t *size) {
+ Mutex::Autolock autoLock(mLock);
+
if (mFd < 0) {
return NO_INIT;
}
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 5429c0c..f0b5958 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -137,3 +137,10 @@
# [ 8- 3] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
# [ 2- 0] Network type (as defined by ConnectivityManager)
50020 connectivity_state_changed (custom|1|5)
+
+
+# ---------------------------
+# NetworkStatsService.java
+# ---------------------------
+51100 netstats_mobile_sample (iface_rx|2|2),(iface_tx|2|2),(uid_rx|2|2),(uid_tx|2|2)
+51101 netstats_wifi_sample (iface_rx|2|2),(iface_tx|2|2),(uid_rx|2|2),(uid_tx|2|2)
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index bb831f5..0e1a1e3 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -655,7 +655,7 @@
List<InputMethodSubtype> enabledSubtypes =
mSettings.getEnabledInputMethodSubtypeListLocked(imi);
if (allowsImplicitlySelectedSubtypes && enabledSubtypes.isEmpty()) {
- enabledSubtypes = getApplicableSubtypesLocked(mRes, getSubtypes(imi));
+ enabledSubtypes = getImplicitlyApplicableSubtypesLocked(mRes, imi);
}
return InputMethodSubtype.sort(mContext, 0, imi, enabledSubtypes);
}
@@ -1668,13 +1668,13 @@
}
@Override
- public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
+ public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
// By this IPC call, only a process which shares the same uid with the IME can add
// additional input method subtypes to the IME.
- if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return false;
+ if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
synchronized (mMethodMap) {
final InputMethodInfo imi = mMethodMap.get(imiId);
- if (imi == null) return false;
+ if (imi == null) return;
final PackageManager pm = mContext.getPackageManager();
final String[] packageInfos = pm.getPackagesForUid(Binder.getCallingUid());
if (packageInfos != null) {
@@ -1688,12 +1688,12 @@
} finally {
Binder.restoreCallingIdentity(ident);
}
- return true;
+ return;
}
}
}
}
- return false;
+ return;
}
private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
@@ -1903,6 +1903,20 @@
return subtypes;
}
+
+ private static ArrayList<InputMethodSubtype> getOverridingImplicitlyEnabledSubtypes(
+ InputMethodInfo imi, String mode) {
+ ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ final int subtypeCount = imi.getSubtypeCount();
+ for (int i = 0; i < subtypeCount; ++i) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ if (subtype.overridesImplicitlyEnabledSubtype() && subtype.getMode().equals(mode)) {
+ subtypes.add(subtype);
+ }
+ }
+ return subtypes;
+ }
+
private boolean chooseNewDefaultIMELocked() {
List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
if (enabled != null && enabled.size() > 0) {
@@ -2357,8 +2371,9 @@
return NOT_A_SUBTYPE_ID;
}
- private static ArrayList<InputMethodSubtype> getApplicableSubtypesLocked(
- Resources res, List<InputMethodSubtype> subtypes) {
+ private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
+ Resources res, InputMethodInfo imi) {
+ final List<InputMethodSubtype> subtypes = getSubtypes(imi);
final String systemLocale = res.getConfiguration().locale.toString();
if (TextUtils.isEmpty(systemLocale)) return new ArrayList<InputMethodSubtype>();
HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
@@ -2366,6 +2381,19 @@
final int N = subtypes.size();
boolean containsKeyboardSubtype = false;
for (int i = 0; i < N; ++i) {
+ // scan overriding implicitly enabled subtypes.
+ InputMethodSubtype subtype = subtypes.get(i);
+ if (subtype.overridesImplicitlyEnabledSubtype()) {
+ final String mode = subtype.getMode();
+ if (!applicableModeAndSubtypesMap.containsKey(mode)) {
+ applicableModeAndSubtypesMap.put(mode, subtype);
+ }
+ }
+ }
+ if (applicableModeAndSubtypesMap.size() > 0) {
+ return new ArrayList<InputMethodSubtype>(applicableModeAndSubtypesMap.values());
+ }
+ for (int i = 0; i < N; ++i) {
InputMethodSubtype subtype = subtypes.get(i);
final String locale = subtype.getLocale();
final String mode = subtype.getMode();
@@ -2489,16 +2517,21 @@
subtype = findLastResortApplicableSubtypeLocked(
mRes, enabledSubtypes, mode, null, true);
}
+ final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
+ getOverridingImplicitlyEnabledSubtypes(imi, mode);
+ final ArrayList<InputMethodSubtype> subtypesForSearch =
+ overridingImplicitlyEnabledSubtypes.isEmpty()
+ ? getSubtypes(imi) : overridingImplicitlyEnabledSubtypes;
// 4. Search by the current subtype's locale from all subtypes.
if (subtype == null && mCurrentSubtype != null) {
subtype = findLastResortApplicableSubtypeLocked(
- mRes, getSubtypes(imi), mode, mCurrentSubtype.getLocale(), false);
+ mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
}
// 5. Search by the system locale from all subtypes.
// 6. Search the first enabled subtype matched with mode from all subtypes.
if (subtype == null) {
subtype = findLastResortApplicableSubtypeLocked(
- mRes, getSubtypes(imi), mode, null, true);
+ mRes, subtypesForSearch, mode, null, true);
}
if (subtype != null) {
if (imiId.equals(mCurMethodId)) {
@@ -2945,12 +2978,12 @@
if (explicitlyEnabledSubtypes.size() == 0) {
// If there are no explicitly enabled subtypes, applicable subtypes are
// enabled implicitly.
- InputMethodInfo ime = mMethodMap.get(imeId);
+ InputMethodInfo imi = mMethodMap.get(imeId);
// If IME is enabled and no subtypes are enabled, applicable subtypes
// are enabled implicitly, so needs to treat them to be enabled.
- if (ime != null && ime.getSubtypeCount() > 0) {
+ if (imi != null && imi.getSubtypeCount() > 0) {
List<InputMethodSubtype> implicitlySelectedSubtypes =
- getApplicableSubtypesLocked(mRes, getSubtypes(ime));
+ getImplicitlyApplicableSubtypesLocked(mRes, imi);
if (implicitlySelectedSubtypes != null) {
final int N = implicitlySelectedSubtypes.size();
for (int i = 0; i < N; ++i) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 85d8cece..1497511 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -1033,6 +1033,38 @@
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
final NetworkStats.Entry entry = new NetworkStats.Entry();
+ final HashSet<String> knownIfaces = Sets.newHashSet();
+ final HashSet<String> activeIfaces = Sets.newHashSet();
+
+ // collect any historical stats and active state
+ // TODO: migrate to reading from single file
+ if (mBandwidthControlEnabled) {
+ for (String iface : fileListWithoutNull(mStatsXtIface)) {
+ final File ifacePath = new File(mStatsXtIface, iface);
+
+ final long active = readSingleLongFromFile(new File(ifacePath, "active"));
+ if (active == 1) {
+ knownIfaces.add(iface);
+ activeIfaces.add(iface);
+ } else if (active == 0) {
+ knownIfaces.add(iface);
+ } else {
+ continue;
+ }
+
+ entry.iface = iface;
+ entry.uid = UID_ALL;
+ entry.set = SET_DEFAULT;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
+ entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
+ entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
+ entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
+
+ stats.addValues(entry);
+ }
+ }
+
final ArrayList<String> values = Lists.newArrayList();
BufferedReader reader = null;
@@ -1058,7 +1090,13 @@
entry.txBytes = Long.parseLong(values.get(9));
entry.txPackets = Long.parseLong(values.get(10));
- stats.addValues(entry);
+ if (activeIfaces.contains(entry.iface)) {
+ // combine stats when iface is active
+ stats.combineValues(entry);
+ } else if (!knownIfaces.contains(entry.iface)) {
+ // add stats when iface is unknown
+ stats.addValues(entry);
+ }
} catch (NumberFormatException e) {
Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
}
@@ -1073,24 +1111,6 @@
IoUtils.closeQuietly(reader);
}
- // splice in historical stats not reflected in mStatsIface
- if (mBandwidthControlEnabled) {
- for (String iface : fileListWithoutNull(mStatsXtIface)) {
- final File ifacePath = new File(mStatsXtIface, iface);
-
- entry.iface = iface;
- entry.uid = UID_ALL;
- entry.set = SET_DEFAULT;
- entry.tag = TAG_NONE;
- entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
- entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
- entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
- entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
-
- stats.combineValues(entry);
- }
- }
-
return stats;
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index cbd986f..bbc26d6 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -853,6 +853,14 @@
if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
int oldWakeLockState = mWakeLockState;
mWakeLockState = mLocks.reactivateScreenLocksLocked();
+
+ // Disable proximity sensor if if user presses power key while we are in the
+ // "waiting for proximity sensor to go negative" state.
+ if ((mWakeLockState & SCREEN_ON_BIT) != 0
+ && mProximitySensorActive && mProximityWakeLockCount == 0) {
+ mProximitySensorActive = false;
+ }
+
if (mSpew) {
Slog.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
+ " mWakeLockState=0x"
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index e0dc96f..4d54fd4 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -31,6 +31,8 @@
import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.UID_REMOVED;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
@@ -76,6 +78,7 @@
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.TelephonyManager;
+import android.util.EventLog;
import android.util.NtpTrustedTime;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -83,6 +86,7 @@
import com.android.internal.os.AtomicFile;
import com.android.internal.util.Objects;
+import com.android.server.EventLogTags;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
@@ -387,7 +391,9 @@
entry.uid = UID_ALL;
entry.tag = TAG_NONE;
entry.rxBytes = historyEntry.rxBytes;
+ entry.rxPackets = historyEntry.rxPackets;
entry.txBytes = historyEntry.txBytes;
+ entry.txPackets = historyEntry.txPackets;
stats.combineValues(entry);
}
@@ -716,6 +722,11 @@
Slog.v(TAG, "performPollLocked() took " + duration + "ms");
}
+ // sample stats after detailed poll
+ if (detailedPoll) {
+ performSample();
+ }
+
// finally, dispatch updated event to any listeners
final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -809,6 +820,33 @@
}
/**
+ * Sample recent statistics summary into {@link EventLog}.
+ */
+ private void performSample() {
+ // take sample as total over last 4 hours
+ final long end = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
+ final long start = end - (4 * HOUR_IN_MILLIS);
+
+ NetworkTemplate template = null;
+ NetworkStats.Entry ifaceTotal = null;
+ NetworkStats.Entry uidTotal = null;
+
+ // collect mobile sample
+ template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
+ ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
+ uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
+ EventLogTags.writeNetstatsMobileSample(
+ ifaceTotal.rxBytes, ifaceTotal.txBytes, uidTotal.rxBytes, uidTotal.txBytes);
+
+ // collect wifi sample
+ template = buildTemplateWifi();
+ ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
+ uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
+ EventLogTags.writeNetstatsWifiSample(
+ ifaceTotal.rxBytes, ifaceTotal.txBytes, uidTotal.rxBytes, uidTotal.txBytes);
+ }
+
+ /**
* Clean up {@link #mUidStats} after UID is removed.
*/
private void removeUidLocked(int uid) {
@@ -1249,6 +1287,12 @@
}
};
+ private static String getActiveSubscriberId(Context context) {
+ final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ return telephony.getSubscriberId();
+ }
+
/**
* Key uniquely identifying a {@link NetworkStatsHistory} for a UID.
*/
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
index ecf78d9..2a25866 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -106,6 +106,7 @@
public void testNetworkStatsSummaryDown() throws Exception {
stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+ stageLong(1L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/active"));
stageLong(1024L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_bytes"));
stageLong(128L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_packets"));
stageLong(2048L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_bytes"));
@@ -119,6 +120,7 @@
public void testNetworkStatsCombined() throws Exception {
stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+ stageLong(1L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/active"));
stageLong(10L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_bytes"));
stageLong(20L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_packets"));
stageLong(30L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_bytes"));
@@ -129,6 +131,18 @@
2205L + 20L, 489339L + 30L, 2237L + 40L);
}
+ public void testNetworkStatsCombinedInactive() throws Exception {
+ stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+ stageLong(0L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/active"));
+ stageLong(10L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_bytes"));
+ stageLong(20L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_packets"));
+ stageLong(30L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_bytes"));
+ stageLong(40L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_packets"));
+
+ final NetworkStats stats = mService.getNetworkStatsSummary();
+ assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 10L, 20L, 30L, 40L);
+ }
+
public void testKernelTags() throws Exception {
assertEquals("0", tagToKernel(0x0));
assertEquals("214748364800", tagToKernel(0x32));
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 23e0ca1..2a52888 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -107,10 +107,9 @@
}
- public boolean setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1)
+ public void setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1)
throws RemoteException {
// TODO Auto-generated method stub
- return false;
}
public boolean setCurrentInputMethodSubtype(InputMethodSubtype arg0) throws RemoteException {
@@ -187,11 +186,4 @@
// TODO Auto-generated method stub
return null;
}
-
- public boolean setAdditionalInputMethodSubtypes(IBinder arg0, InputMethodSubtype[] arg1)
- throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
}
diff --git a/wifi/java/android/net/wifi/WpsConfiguration.java b/wifi/java/android/net/wifi/WpsConfiguration.java
index 2e7689a..0c2adfd 100644
--- a/wifi/java/android/net/wifi/WpsConfiguration.java
+++ b/wifi/java/android/net/wifi/WpsConfiguration.java
@@ -46,16 +46,21 @@
public Setup setup;
+ /** @hide */
public String BSSID;
public String pin;
+ /** @hide */
public IpAssignment ipAssignment;
+ /** @hide */
public ProxySettings proxySettings;
+ /** @hide */
public LinkProperties linkProperties;
+ /** @hide */
public WpsConfiguration() {
setup = Setup.INVALID;
BSSID = null;
@@ -65,6 +70,7 @@
linkProperties = new LinkProperties();
}
+ /** @hide */
public String toString() {
StringBuffer sbuf = new StringBuffer();
sbuf.append(" setup: ").append(setup.toString());
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 2d57363..686d698 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -28,11 +28,6 @@
public class WifiP2pConfig implements Parcelable {
/**
- * Device name
- */
- public String deviceName;
-
- /**
* Device address
*/
public String deviceAddress;
@@ -53,6 +48,7 @@
/**
* Indicates whether the configuration is saved
+ * @hide
*/
public enum Persist {
SYSTEM_DEFAULT,
@@ -60,6 +56,7 @@
NO
}
+ /** @hide */
public Persist persist = Persist.SYSTEM_DEFAULT;
public WifiP2pConfig() {
@@ -110,7 +107,6 @@
public String toString() {
StringBuffer sbuf = new StringBuffer();
- sbuf.append("Device: ").append(deviceName);
sbuf.append("\n address: ").append(deviceAddress);
sbuf.append("\n wps: ").append(wpsConfig);
sbuf.append("\n groupOwnerIntent: ").append(groupOwnerIntent);
@@ -132,7 +128,6 @@
/** Implement the Parcelable interface {@hide} */
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(deviceName);
dest.writeString(deviceAddress);
dest.writeParcelable(wpsConfig, flags);
dest.writeInt(groupOwnerIntent);
@@ -144,7 +139,6 @@
new Creator<WifiP2pConfig>() {
public WifiP2pConfig createFromParcel(Parcel in) {
WifiP2pConfig config = new WifiP2pConfig();
- config.deviceName = in.readString();
config.deviceAddress = in.readString();
config.wpsConfig = (WpsConfiguration) in.readParcelable(null);
config.groupOwnerIntent = in.readInt();
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index ca6e4d5..14246b4 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -69,7 +69,7 @@
}
/**
- * @param string formats supported include
+ * @param supplicantEvent formats supported include
*
* P2P-GROUP-STARTED p2p-wlan0-0 [client|GO] ssid="DIRECT-W8" freq=2437
* [psk=2182b2e50e53f260d04f3c7b25ef33c965a3291b9b36b455a82d77fd82ca15bc|
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
index 9dc2fbf..a02175e 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
@@ -34,9 +34,11 @@
public InetAddress groupOwnerAddress;
- public WifiP2pInfo() {
+ /** @hide */
+ WifiP2pInfo() {
}
+ /** @hide */
public String toString() {
StringBuffer sbuf = new StringBuffer();
sbuf.append("groupFormed: ").append(groupFormed)
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 25daf1c..0bdd269 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -35,25 +35,64 @@
import com.android.internal.util.Protocol;
/**
- * This class provides the API for managing Wi-Fi p2p
- * connectivity. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String)
+ * This class provides the API for managing Wi-Fi peer-to-peer connectivity. This lets an
+ * application discover available peers, setup connection to peers and query for the list of peers.
+ * When a p2p connection is formed over wifi, the device continues to maintain the uplink
+ * connection over mobile or any other available network for internet connectivity on the device.
+ *
+ * <p> The API is asynchronous and response to a request from an application is sent in the form
+ * of a {@link android.os.Message} on a {@link android.os.Handler} that needs to be initialized
+ * by the application right at the beginning before any p2p operations are performed via
+ * {@link #initialize}.
+ *
+ * <p> An application can request for the current list of peers using {@link #requestPeers}. The
+ * {@link #RESPONSE_PEERS} message on the handler indicates that the peer list is available.
+ * Use {@link #peersInResponse} to extract the peer device list upon the receiving the
+ * {@link #RESPONSE_PEERS} message.
+ *
+ * <p> If an application needs to initiate a discovery, use {@link #discoverPeers} and listen
+ * to {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent action to initiate a request to fetch
+ * list of peers with {@link #requestPeers}. An initiated discovery request from an application
+ * stays active until the device starts connecting to a peer or forms a p2p group.
+ *
+ * <p> An application can initiate a connection request to a peer through {@link #connect}. See
+ * {@link WifiP2pConfig} for details on setting up the configuration. For communication with legacy
+ * Wi-Fi devices that do not support p2p, an app can create a group using {@link #createGroup}
+ * which creates an access point whose details can be fetched with {@link #requestGroupInfo}.
+ *
+ * <p> After a successful group formation through {@link #createGroup} or through {@link #connect},
+ * use {@link #requestConnectionInfo} to fetch the connection details. Connection information
+ * can be obtained with {@link #connectionInfoInResponse} on a {@link #RESPONSE_CONNECTION_INFO}
+ * message. The connection info {@link WifiP2pInfo} contains the address of the group owner
+ * {@link WifiP2pInfo#groupOwnerAddress} and a flag {@link #WifiP2pInfo#isGroupOwner} to indicate
+ * if the current device is a p2p group owner. A p2p client can thus communicate with
+ * the p2p group owner through a socket connection.
+ *
+ * <p> Android has no platform support for service discovery yet, so applications could
+ * run a service discovery protocol to discover services on the peer-to-peer netework.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Registering an application handler with {@link #initialize} requires the permissions
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer
+ * operations.
+ *
+ * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
* Context.getSystemService(Context.WIFI_P2P_SERVICE)}.
*
- * It deals with the following:
- * <ul>
- * <li>Wi-Fi peer discovery and connection setup. Allows applications to initiate a discovery to
- * find available peers and then setup a connection </li>
- * <li>Configuration and status query. Allows applications to fetch the current list
- * of available and connected peers and query connection status </li>
- * <li>Intent actions that are broadcast to track operations
- * on a p2p connection</li>
- * </ul>
+ * {@see WifiP2pConfig}
+ * {@see WifiP2pInfo}
+ * {@see WifiP2pGroup}
+ * {@see WifiP2pDevice}
+ * {@see WifiP2pDeviceList}
* @hide
*/
public class WifiP2pManager {
/**
- * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled.
+ * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. An
+ * extra {@link #EXTRA_WIFI_STATE} provides the state information as int.
+ *
+ * @see #EXTRA_WIFI_STATE
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String WIFI_P2P_STATE_CHANGED_ACTION =
@@ -72,7 +111,6 @@
* Wi-Fi p2p is disabled.
*
* @see #WIFI_P2P_STATE_CHANGED_ACTION
- * @see #getWifiP2pState()
*/
public static final int WIFI_P2P_STATE_DISABLED = 1;
@@ -80,14 +118,16 @@
* Wi-Fi p2p is enabled.
*
* @see #WIFI_P2P_STATE_CHANGED_ACTION
- * @see #getWifiP2pState()
*/
public static final int WIFI_P2P_STATE_ENABLED = 2;
/**
* Broadcast intent action indicating that the state of Wi-Fi p2p connectivity
- * has changed. One extra provides the new state
- * in the form of a {@link android.net.NetworkInfo} object.
+ * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in
+ * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides
+ * the network info in the form of a {@link android.net.NetworkInfo}.
+ *
+ * @see #EXTRA_WIFI_P2P_INFO
* @see #EXTRA_NETWORK_INFO
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -124,7 +164,8 @@
public static final String EXTRA_LINK_CAPABILITIES = "linkCapabilities";
/**
- * Broadcast intent action indicating that the available peer list has changed
+ * Broadcast intent action indicating that the available peer list has changed. Fetch
+ * the changed list of peers with {@link #requestPeers}
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String WIFI_P2P_PEERS_CHANGED_ACTION =
@@ -134,6 +175,7 @@
* Activity Action: Pick a Wi-Fi p2p network to connect to.
* <p>Input: Nothing.
* <p>Output: Nothing.
+ * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PICK_WIFI_P2P_NETWORK =
@@ -141,47 +183,169 @@
IWifiP2pManager mService;
- /* AsyncChannel notifications to apps */
- public static final int HANDLER_CONNECTION = AsyncChannel.CMD_CHANNEL_HALF_CONNECTED;
+ /**
+ * Message {@link android.os.Message#what} sent on the application handler specified
+ * at {@link #initialize} indicating the asynchronous channel has disconnected. An
+ * application could choose to reconnect with {@link #initialize}
+ */
public static final int HANDLER_DISCONNECTION = AsyncChannel.CMD_CHANNEL_DISCONNECTED;
private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
+ /** @hide */
public static final int ENABLE_P2P = BASE + 1;
+ /** @hide */
public static final int ENABLE_P2P_FAILED = BASE + 2;
+ /** @hide */
public static final int ENABLE_P2P_SUCCEEDED = BASE + 3;
+ /** @hide */
public static final int DISABLE_P2P = BASE + 4;
+ /** @hide */
public static final int DISABLE_P2P_FAILED = BASE + 5;
+ /** @hide */
public static final int DISABLE_P2P_SUCCEEDED = BASE + 6;
+ /** @hide */
public static final int DISCOVER_PEERS = BASE + 7;
+
+ /**
+ * Message {@link android.os.Message#what} value indicating that the {@link #discoverPeers}
+ * operation failed.
+ * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
+ * or {@link #ALREADY_IN_EFFECT}
+ */
public static final int DISCOVER_PEERS_FAILED = BASE + 8;
+ /**
+ * Message {@link android.os.Message#what} value indicating that the {@link #discoverPeers}
+ * operation succeeded.
+ * <p> The application can register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent
+ * to listen for changes in the peer list as a result of the discovery process.
+ */
public static final int DISCOVER_PEERS_SUCCEEDED = BASE + 9;
+ /** @hide */
public static final int CONNECT = BASE + 10;
+
+ /**
+ * Message {@link android.os.Message#what} value indicating that the {@link #connect}
+ * operation failed.
+ * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
+ * or {@link #ALREADY_IN_EFFECT}
+ */
public static final int CONNECT_FAILED = BASE + 11;
+ /**
+ * Message {@link android.os.Message#what} value indicating that the {@link #connect}
+ * operation succeeded.
+ * <p> The application can register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent
+ * to listen for connectivity change as a result of the connect operation
+ */
public static final int CONNECT_SUCCEEDED = BASE + 12;
+ /** @hide */
public static final int CREATE_GROUP = BASE + 13;
+
+ /**
+ * Message {@link android.os.Message#what} value indicating that the {@link #createGroup}
+ * operation failed.
+ * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
+ * or {@link #ALREADY_IN_EFFECT}
+ */
public static final int CREATE_GROUP_FAILED = BASE + 14;
+ /**
+ * Message {@link android.os.Message#what} value indicating that the {@link #createGroup}
+ * operation succeeded.
+ * <p> The application can request the group details with {@link #requestGroupInfo}
+ */
public static final int CREATE_GROUP_SUCCEEDED = BASE + 15;
+ /** @hide */
public static final int REMOVE_GROUP = BASE + 16;
+ /**
+ * Message {@link android.os.Message#what} value indicating that the {@link #removeGroup}
+ * operation failed.
+ * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
+ * or {@link #ALREADY_IN_EFFECT}
+ */
public static final int REMOVE_GROUP_FAILED = BASE + 17;
+ /**
+ * Message {@link android.os.Message#what} value indicating that the {@link #removeGroup}
+ * operation succeeded.
+ */
public static final int REMOVE_GROUP_SUCCEEDED = BASE + 18;
- public static final int REQUEST_PEERS = BASE + 19;
- public static final int RESPONSE_PEERS = BASE + 20;
-
- public static final int REQUEST_CONNECTION_INFO = BASE + 21;
- public static final int RESPONSE_CONNECTION_INFO = BASE + 22;
-
- /* arg1 values on response messages from the framework */
+ /**
+ * Supported {@link android.os.Message#arg1} value on the following response messages:
+ * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
+ * and {@link #REMOVE_GROUP_FAILED}
+ *
+ * <p> This indicates that the reason for failure is because p2p is unsupported on the
+ * device
+ */
public static final int P2P_UNSUPPORTED = 1;
+ /**
+ * Supported {@link android.os.Message#arg1} value on the following response messages:
+ * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
+ * and {@link #REMOVE_GROUP_FAILED}
+ *
+ * <p> This indicates that the reason for failure is because p2p is currently disabled
+ * by the user
+ */
+ public static final int P2P_DISABLED = 2;
+
+ /**
+ * Supported {@link android.os.Message#arg1} value on the following response messages:
+ * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
+ * and {@link #REMOVE_GROUP_FAILED}
+ *
+ * <p> This indicates that the reason for failure is because the operation is already in
+ * effect
+ */
+ public static final int ALREADY_IN_EFFECT = 3;
+
+
+ /** @hide */
+ public static final int REQUEST_PEERS = BASE + 19;
+ /**
+ * Message {@link android.os.Message#what} delivered on the application hander
+ * in response to a {@link #requestPeers} call from the application.
+ *
+ * <p> Extract a {@link WifiP2pDeviceList} object by calling {@link #peersInResponse}
+ * on the message object
+ */
+ public static final int RESPONSE_PEERS = BASE + 20;
+
+ /** @hide */
+ public static final int REQUEST_CONNECTION_INFO = BASE + 21;
+
+ /**
+ * Message {@link android.os.Message#what} delivered on the application hander
+ * in response to a {@link #requestConnectionInfo} call from the application.
+ *
+ * <p> Extract a {@link WifiP2pInfo} object by calling {@link #connectionInfoInResponse}
+ * on the message object
+ */
+ public static final int RESPONSE_CONNECTION_INFO = BASE + 22;
+
+ /** @hide */
+ public static final int REQUEST_GROUP_INFO = BASE + 23;
+
+ /**
+ * Message {@link android.os.Message#what} delivered on the application hander
+ * in response to a {@link #requestGroupInfo} call from the application.
+ *
+ * <p> Extract a {@link WifiP2pGroup} object by calling {@link #groupInfoInResponse}
+ * on the message object
+ */
+
+ public static final int RESPONSE_GROUP_INFO = BASE + 24;
+
+ /** @hide */
public static final int WPS_PBC = BASE + 23;
+ /** @hide */
public static final int WPS_PIN = BASE + 24;
+ /** @hide */
public static final int WPS_PIN_AVAILABLE = BASE + 25;
/**
@@ -199,7 +363,8 @@
/**
* A channel that connects the application handler to the Wifi framework.
- * All p2p operations are performed on a channel.
+ * Most p2p operations require a Channel as an argument. An instance of Channel is obtained
+ * by doing a call on {@link #initialize}
*/
public class Channel {
Channel(AsyncChannel c) {
@@ -210,10 +375,17 @@
/**
* 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.
+ * must be the first to be called before any p2p operations are performed.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * The handler registered with the framework should only handle messages
+ * with {@link android.os.Message#what} values defined in this file. Adding application
+ * specific private {@link android.os.Message#what} types should be done on a seperate handler
+ *
* @param srcContext is the context of the source
- * @param srcHandler is the handler on which the source receives messages
- * @return Channel instance that is necessary for performing p2p operations
+ * @param srcHandler is the handler on which the source will receive message responses
+ * asynchronously
+ * @return Channel instance that is necessary for performing any further p2p operations
*/
public Channel initialize(Context srcContext, Handler srcHandler) {
Messenger messenger = getMessenger();
@@ -229,6 +401,7 @@
}
}
+ /** @hide */
public boolean isP2pSupported() {
try {
return mService.isP2pSupported();
@@ -240,6 +413,7 @@
/**
* 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.
+ * @hide
*/
public void enableP2p(Channel c) {
if (c == null) return;
@@ -249,6 +423,7 @@
/**
* 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.
+ * @hide
*/
public void disableP2p(Channel c) {
if (c == null) return;
@@ -256,7 +431,22 @@
}
/**
- * Initiates peer discovery
+ * Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers
+ * for the purpose of establishing a connection.
+ *
+ * <p> The function call immediately returns after sending a discovery request
+ * to the framework. The application handler is notified of a success or failure to initiate
+ * discovery with {@link #DISCOVER_PEERS_SUCCEEDED} or {@link #DISCOVER_PEERS_FAILED}.
+ *
+ * <p> The discovery remains active until a connection is initiated or
+ * a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
+ * determine when the framework notifies of a change as peers are discovered.
+ *
+ * <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
+ * can request for the list of peers using {@link #requestPeers} which will deliver a
+ * {@link #RESPONSE_PEERS} message on the application handler. The application can then
+ * extract a {@link WifiP2pDeviceList} object by calling {@link #peersInResponse}
+ * on the message.
*/
public void discoverPeers(Channel c) {
if (c == null) return;
@@ -264,9 +454,23 @@
}
/**
- * Start a p2p connection
+ * Start a p2p connection to a device with the specified configuration.
*
- * @param peer Configuration described in a {@link WifiP2pConfig} object.
+ * <p> The function call immediately returns after sending a connection request
+ * to the framework. The application handler is notified of a success or failure to initiate
+ * connectivity with {@link #CONNECT_SUCCEEDED} or {@link #CONNECT_FAILED}.
+ *
+ * <p> Register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent to
+ * determine when the framework notifies of a change in connectivity.
+ *
+ * <p> If the current device is not part of a p2p group, a connect request initiates
+ * a group negotiation with the peer.
+ *
+ * <p> If the current device is part of an existing p2p group or has created
+ * a p2p group with {@link #createGroup}, an invitation to join the group is sent to
+ * the peer device.
+ *
+ * @param config options as described in {@link WifiP2pConfig} class.
*/
public void connect(Channel c, WifiP2pConfig config) {
if (c == null) return;
@@ -274,8 +478,20 @@
}
/**
- * Create a p2p group. This is essentially an access point that can accept
- * client connections.
+ * Create a p2p group with the current device as the group owner. This essentially creates
+ * an access point that can accept connections from legacy clients as well as other p2p
+ * devices.
+ * <p> For p2p operation, this would normally not be used unless the current device needs
+ * to form a p2p connection with a legacy client
+ *
+ * <p> The function call immediately returns after sending a group creation request
+ * to the framework. The application handler is notified of a success or failure to create
+ * group with {@link #CREATE_GROUP_SUCCEEDED} or {@link #CREATE_GROUP_FAILED}.
+ *
+ * <p> Application can request for the group details with {@link #requestGroupInfo} which will
+ * deliver a {@link #RESPONSE_GROUP_INFO} message on the application handler. The application
+ * can then extract a {@link WifiP2pGroup} object by calling {@link #groupInfoInResponse}
+ * on the message.
*/
public void createGroup(Channel c) {
if (c == null) return;
@@ -283,8 +499,11 @@
}
/**
- * Remove the current group. This also removes the p2p interface created
- * during group formation.
+ * Remove the current p2p group.
+ *
+ * <p> The function call immediately returns after sending a group removal request
+ * to the framework. The application handler is notified of a success or failure to remove
+ * a group with {@link #REMOVE_GROUP_SUCCEEDED} or {@link #REMOVE_GROUP_FAILED}.
*/
public void removeGroup(Channel c) {
if (c == null) return;
@@ -292,8 +511,9 @@
}
/**
- * Request the list of peers. This returns a RESPONSE_PEERS on the source
- * handler.
+ * Request the current list of peers. This returns a {@link #RESPONSE_PEERS} on the application
+ * handler. The {@link #RESPONSE_PEERS} message on the handler indicates that the peer list is
+ * available. Use {@link #peersInResponse} to extract {@link WifiP2pDeviceList} from the message
*/
public void requestPeers(Channel c) {
if (c == null) return;
@@ -301,15 +521,18 @@
}
/**
- * Fetch device list from a RESPONSE_PEERS message
+ * Upon receiving a {@link #RESPONSE_PEERS} on the application handler, an application
+ * can extract the peer device list using this function.
*/
public WifiP2pDeviceList peersInResponse(Message msg) {
return (WifiP2pDeviceList) msg.obj;
}
/**
- * Request device connection info. This returns a RESPONSE_CONNECTION_INFO on
- * the source handler.
+ * Request device connection info. This returns a {@link #RESPONSE_CONNECTION_INFO} on
+ * the application handler. The {@link #RESPONSE_CONNECTION_INFO} message on the handler
+ * indicates that connection info is available. Use {@link #connectionInfoInResponse} to
+ * extract {@link WifiP2pInfo} from the message.
*/
public void requestConnectionInfo(Channel c) {
if (c == null) return;
@@ -317,12 +540,31 @@
}
/**
- * Fetch p2p connection status from a RESPONSE_CONNECTION_INFO message
+ * Upon receiving a {@link #RESPONSE_CONNECTION_INFO} on the application handler, an application
+ * can extract the connection info using this function.
*/
public WifiP2pInfo connectionInfoInResponse(Message msg) {
return (WifiP2pInfo) msg.obj;
}
+ /**
+ * Request p2p group info. This returns a {@link #RESPONSE_GROUP_INFO} on
+ * the application handler. The {@link #RESPONSE_GROUP_INFO} message on the handler
+ * indicates that group info is available. Use {@link #groupInfoInResponse} to
+ * extract {@link WifiP2pGroup} from the message.
+ */
+ public void requestGroupInfo(Channel c) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(REQUEST_GROUP_INFO);
+ }
+
+ /**
+ * Upon receiving a {@link #RESPONSE_GROUP_INFO} on the application handler, an application
+ * can extract the group info using this function.
+ */
+ public WifiP2pGroup groupInfoInResponse(Message msg) {
+ return (WifiP2pGroup) msg.obj;
+ }
/**
* Get a reference to WifiP2pService handler. This is used to establish
@@ -339,7 +581,6 @@
}
}
-
/**
* Setup DNS connectivity on the current process to the connected Wi-Fi p2p peers
*