Merge change 2658
* changes:
Delete the acc script when deleting the Renderscript rsScriptC object.
diff --git a/api/current.xml b/api/current.xml
index 4db6e66..f93fefd 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -309,6 +309,17 @@
visibility="public"
>
</field>
+<field name="CHANGE_WIFI_MULTICAST_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.permission.CHANGE_WIFI_MULTICAST_STATE""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="CHANGE_WIFI_STATE"
type="java.lang.String"
transient="false"
@@ -80263,6 +80274,19 @@
<parameter name="rssiB" type="int">
</parameter>
</method>
+<method name="createMulticastLock"
+ return="android.net.wifi.WifiManager.MulticastLock"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
<method name="createWifiLock"
return="android.net.wifi.WifiManager.WifiLock"
abstract="false"
@@ -80755,6 +80779,48 @@
>
</field>
</class>
+<class name="WifiManager.MulticastLock"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="acquire"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isHeld"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="release"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
<class name="WifiManager.WifiLock"
extends="java.lang.Object"
abstract="false"
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3c827a0..20e2c46 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3865,8 +3865,7 @@
mRecognizer = LetterRecognizer.getLetterRecognizer(getContext(),
LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE);
if (mRecognizer == null) {
- dismissGesturesPopup();
- mGestures = GESTURES_NONE;
+ setGestures(GESTURES_NONE);
}
if (mGestures == GESTURES_FILTER) {
mKeyMap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b97e07b..0a24bb7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -644,6 +644,13 @@
android:description="@string/permdesc_changeWifiState"
android:label="@string/permlab_changeWifiState" />
+ <!-- Allows applications to enter Wi-Fi Multicast mode -->
+ <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="dangerous"
+ android:description="@string/permdesc_changeWifiMulticastState"
+ android:label="@string/permlab_changeWifiMulticastState" />
+
<!-- Allows applications to discover and pair bluetooth devices -->
<permission android:name="android.permission.BLUETOOTH_ADMIN"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
diff --git a/core/res/res/raw/latin_lowercase b/core/res/res/raw/latin_lowercase
index 17cfaf0..443d5f8 100644
--- a/core/res/res/raw/latin_lowercase
+++ b/core/res/res/raw/latin_lowercase
Binary files differ
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6512006..39485e2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1012,6 +1012,15 @@
configured Wi-Fi networks.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_changeWifiMulticastState">allow Wi-Fi Multicast
+ reception</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_changeWifiMulticastState">Allows an application to
+ receive packets not directly addressed to your device. This can be
+ useful when discovering services offered near by. It uses more power
+ than the non-multicast mode.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_bluetoothAdmin">bluetooth administration</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bluetoothAdmin">Allows an application to configure
diff --git a/docs/html/shareables/icon_templates-v1.0.zip b/docs/html/shareables/icon_templates-v1.0.zip
index 3e64f9aa..94fbcdc 100644
--- a/docs/html/shareables/icon_templates-v1.0.zip
+++ b/docs/html/shareables/icon_templates-v1.0.zip
Binary files differ
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 30b6733..afad48e 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -55,7 +55,6 @@
#
hostSources:= \
InetAddress.cpp \
- Pipe.cpp \
Socket.cpp \
ZipEntry.cpp \
ZipFile.cpp
@@ -71,12 +70,7 @@
# Use the futex based mutex and condition variable
# implementation from android-arm because it's shared mem safe
LOCAL_SRC_FILES += \
- futex_synchro.c \
- executablepath_linux.cpp
-endif
-ifeq ($(HOST_OS),darwin)
- LOCAL_SRC_FILES += \
- executablepath_darwin.cpp
+ futex_synchro.c
endif
LOCAL_MODULE:= libutils
diff --git a/libs/utils/Pipe.cpp b/libs/utils/Pipe.cpp
deleted file mode 100644
index 613906b..0000000
--- a/libs/utils/Pipe.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (C) 2005 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-// Unidirectional pipe.
-//
-
-#include <utils/Pipe.h>
-#include <utils/Log.h>
-
-#if defined(HAVE_WIN32_IPC)
-# include <windows.h>
-#else
-# include <fcntl.h>
-# include <unistd.h>
-# include <errno.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-
-using namespace android;
-
-const unsigned long kInvalidHandle = (unsigned long) -1;
-
-
-/*
- * Constructor. Do little.
- */
-Pipe::Pipe(void)
- : mReadNonBlocking(false), mReadHandle(kInvalidHandle),
- mWriteHandle(kInvalidHandle)
-{
-}
-
-/*
- * Destructor. Use the system-appropriate close call.
- */
-Pipe::~Pipe(void)
-{
-#if defined(HAVE_WIN32_IPC)
- if (mReadHandle != kInvalidHandle) {
- if (!CloseHandle((HANDLE)mReadHandle))
- LOG(LOG_WARN, "pipe", "failed closing read handle (%ld)\n",
- mReadHandle);
- }
- if (mWriteHandle != kInvalidHandle) {
- FlushFileBuffers((HANDLE)mWriteHandle);
- if (!CloseHandle((HANDLE)mWriteHandle))
- LOG(LOG_WARN, "pipe", "failed closing write handle (%ld)\n",
- mWriteHandle);
- }
-#else
- if (mReadHandle != kInvalidHandle) {
- if (close((int) mReadHandle) != 0)
- LOG(LOG_WARN, "pipe", "failed closing read fd (%d)\n",
- (int) mReadHandle);
- }
- if (mWriteHandle != kInvalidHandle) {
- if (close((int) mWriteHandle) != 0)
- LOG(LOG_WARN, "pipe", "failed closing write fd (%d)\n",
- (int) mWriteHandle);
- }
-#endif
-}
-
-/*
- * Create the pipe.
- *
- * Use the POSIX stuff for everything but Windows.
- */
-bool Pipe::create(void)
-{
- assert(mReadHandle == kInvalidHandle);
- assert(mWriteHandle == kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
- /* we use this across processes, so they need to be inheritable */
- HANDLE handles[2];
- SECURITY_ATTRIBUTES saAttr;
-
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = NULL;
-
- if (!CreatePipe(&handles[0], &handles[1], &saAttr, 0)) {
- LOG(LOG_ERROR, "pipe", "unable to create pipe\n");
- return false;
- }
- mReadHandle = (unsigned long) handles[0];
- mWriteHandle = (unsigned long) handles[1];
- return true;
-#else
- int fds[2];
-
- if (pipe(fds) != 0) {
- LOG(LOG_ERROR, "pipe", "unable to create pipe\n");
- return false;
- }
- mReadHandle = fds[0];
- mWriteHandle = fds[1];
- return true;
-#endif
-}
-
-/*
- * Create a "half pipe". Please, no Segway riding.
- */
-bool Pipe::createReader(unsigned long handle)
-{
- mReadHandle = handle;
- assert(mWriteHandle == kInvalidHandle);
- return true;
-}
-
-/*
- * Create a "half pipe" for writing.
- */
-bool Pipe::createWriter(unsigned long handle)
-{
- mWriteHandle = handle;
- assert(mReadHandle == kInvalidHandle);
- return true;
-}
-
-/*
- * Return "true" if create() has been called successfully.
- */
-bool Pipe::isCreated(void)
-{
- // one or the other should be open
- return (mReadHandle != kInvalidHandle || mWriteHandle != kInvalidHandle);
-}
-
-
-/*
- * Read data from the pipe.
- *
- * For Linux and Darwin, just call read(). For Windows, implement
- * non-blocking reads by calling PeekNamedPipe first.
- */
-int Pipe::read(void* buf, int count)
-{
- assert(mReadHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
- DWORD totalBytesAvail = count;
- DWORD bytesRead;
-
- if (mReadNonBlocking) {
- // use PeekNamedPipe to adjust read count expectations
- if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL,
- &totalBytesAvail, NULL))
- {
- LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n");
- return -1;
- }
-
- if (totalBytesAvail == 0)
- return 0;
- }
-
- if (!ReadFile((HANDLE) mReadHandle, buf, totalBytesAvail, &bytesRead,
- NULL))
- {
- DWORD err = GetLastError();
- if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE)
- return 0;
- LOG(LOG_ERROR, "pipe", "ReadFile failed (err=%ld)\n", err);
- return -1;
- }
-
- return (int) bytesRead;
-#else
- int cc;
- cc = ::read(mReadHandle, buf, count);
- if (cc < 0 && errno == EAGAIN)
- return 0;
- return cc;
-#endif
-}
-
-/*
- * Write data to the pipe.
- *
- * POSIX systems are trivial, Windows uses a different call and doesn't
- * handle non-blocking writes.
- *
- * If we add non-blocking support here, we probably want to make it an
- * all-or-nothing write.
- *
- * DO NOT use LOG() here, we could be writing a log message.
- */
-int Pipe::write(const void* buf, int count)
-{
- assert(mWriteHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
- DWORD bytesWritten;
-
- if (mWriteNonBlocking) {
- // BUG: can't use PeekNamedPipe() to get the amount of space
- // left. Looks like we need to use "overlapped I/O" functions.
- // I just don't care that much.
- }
-
- if (!WriteFile((HANDLE) mWriteHandle, buf, count, &bytesWritten, NULL)) {
- // can't LOG, use stderr
- fprintf(stderr, "WriteFile failed (err=%ld)\n", GetLastError());
- return -1;
- }
-
- return (int) bytesWritten;
-#else
- int cc;
- cc = ::write(mWriteHandle, buf, count);
- if (cc < 0 && errno == EAGAIN)
- return 0;
- return cc;
-#endif
-}
-
-/*
- * Figure out if there is data available on the read fd.
- *
- * We return "true" on error because we want the caller to try to read
- * from the pipe. They'll notice the read failure and do something
- * appropriate.
- */
-bool Pipe::readReady(void)
-{
- assert(mReadHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
- DWORD totalBytesAvail;
-
- if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL,
- &totalBytesAvail, NULL))
- {
- LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n");
- return true;
- }
-
- return (totalBytesAvail != 0);
-#else
- errno = 0;
- fd_set readfds;
- struct timeval tv = { 0, 0 };
- int cc;
-
- FD_ZERO(&readfds);
- FD_SET(mReadHandle, &readfds);
-
- cc = select(mReadHandle+1, &readfds, NULL, NULL, &tv);
- if (cc < 0) {
- LOG(LOG_ERROR, "pipe", "select() failed\n");
- return true;
- } else if (cc == 0) {
- /* timed out, nothing available */
- return false;
- } else if (cc == 1) {
- /* our fd is ready */
- return true;
- } else {
- LOG(LOG_ERROR, "pipe", "HUH? select() returned > 1\n");
- return true;
- }
-#endif
-}
-
-/*
- * Enable or disable non-blocking mode for the read descriptor.
- *
- * NOTE: the calls succeed under Mac OS X, but the pipe doesn't appear to
- * actually be in non-blocking mode. If this matters -- i.e. you're not
- * using a select() call -- put a call to readReady() in front of the
- * ::read() call, with a PIPE_NONBLOCK_BROKEN #ifdef in the Makefile for
- * Darwin.
- */
-bool Pipe::setReadNonBlocking(bool val)
-{
- assert(mReadHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
- // nothing to do
-#else
- int flags;
-
- if (fcntl(mReadHandle, F_GETFL, &flags) == -1) {
- LOG(LOG_ERROR, "pipe", "couldn't get flags for pipe read fd\n");
- return false;
- }
- if (val)
- flags |= O_NONBLOCK;
- else
- flags &= ~(O_NONBLOCK);
- if (fcntl(mReadHandle, F_SETFL, &flags) == -1) {
- LOG(LOG_ERROR, "pipe", "couldn't set flags for pipe read fd\n");
- return false;
- }
-#endif
-
- mReadNonBlocking = val;
- return true;
-}
-
-/*
- * Enable or disable non-blocking mode for the write descriptor.
- *
- * As with setReadNonBlocking(), this does not work on the Mac.
- */
-bool Pipe::setWriteNonBlocking(bool val)
-{
- assert(mWriteHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
- // nothing to do
-#else
- int flags;
-
- if (fcntl(mWriteHandle, F_GETFL, &flags) == -1) {
- LOG(LOG_WARN, "pipe",
- "Warning: couldn't get flags for pipe write fd (errno=%d)\n",
- errno);
- return false;
- }
- if (val)
- flags |= O_NONBLOCK;
- else
- flags &= ~(O_NONBLOCK);
- if (fcntl(mWriteHandle, F_SETFL, &flags) == -1) {
- LOG(LOG_WARN, "pipe",
- "Warning: couldn't set flags for pipe write fd (errno=%d)\n",
- errno);
- return false;
- }
-#endif
-
- mWriteNonBlocking = val;
- return true;
-}
-
-/*
- * Specify whether a file descriptor can be inherited by a child process.
- * Under Linux this means setting the close-on-exec flag, under Windows
- * this is SetHandleInformation(HANDLE_FLAG_INHERIT).
- */
-bool Pipe::disallowReadInherit(void)
-{
- if (mReadHandle == kInvalidHandle)
- return false;
-
-#if defined(HAVE_WIN32_IPC)
- if (SetHandleInformation((HANDLE) mReadHandle, HANDLE_FLAG_INHERIT, 0) == 0)
- return false;
-#else
- if (fcntl((int) mReadHandle, F_SETFD, FD_CLOEXEC) != 0)
- return false;
-#endif
- return true;
-}
-bool Pipe::disallowWriteInherit(void)
-{
- if (mWriteHandle == kInvalidHandle)
- return false;
-
-#if defined(HAVE_WIN32_IPC)
- if (SetHandleInformation((HANDLE) mWriteHandle, HANDLE_FLAG_INHERIT, 0) == 0)
- return false;
-#else
- if (fcntl((int) mWriteHandle, F_SETFD, FD_CLOEXEC) != 0)
- return false;
-#endif
- return true;
-}
-
-/*
- * Close read descriptor.
- */
-bool Pipe::closeRead(void)
-{
- if (mReadHandle == kInvalidHandle)
- return false;
-
-#if defined(HAVE_WIN32_IPC)
- if (mReadHandle != kInvalidHandle) {
- if (!CloseHandle((HANDLE)mReadHandle)) {
- LOG(LOG_WARN, "pipe", "failed closing read handle\n");
- return false;
- }
- }
-#else
- if (mReadHandle != kInvalidHandle) {
- if (close((int) mReadHandle) != 0) {
- LOG(LOG_WARN, "pipe", "failed closing read fd\n");
- return false;
- }
- }
-#endif
- mReadHandle = kInvalidHandle;
- return true;
-}
-
-/*
- * Close write descriptor.
- */
-bool Pipe::closeWrite(void)
-{
- if (mWriteHandle == kInvalidHandle)
- return false;
-
-#if defined(HAVE_WIN32_IPC)
- if (mWriteHandle != kInvalidHandle) {
- if (!CloseHandle((HANDLE)mWriteHandle)) {
- LOG(LOG_WARN, "pipe", "failed closing write handle\n");
- return false;
- }
- }
-#else
- if (mWriteHandle != kInvalidHandle) {
- if (close((int) mWriteHandle) != 0) {
- LOG(LOG_WARN, "pipe", "failed closing write fd\n");
- return false;
- }
- }
-#endif
- mWriteHandle = kInvalidHandle;
- return true;
-}
-
-/*
- * Get the read handle.
- */
-unsigned long Pipe::getReadHandle(void)
-{
- assert(mReadHandle != kInvalidHandle);
-
- return mReadHandle;
-}
-
-/*
- * Get the write handle.
- */
-unsigned long Pipe::getWriteHandle(void)
-{
- assert(mWriteHandle != kInvalidHandle);
-
- return mWriteHandle;
-}
-
diff --git a/libs/utils/executablepath_darwin.cpp b/libs/utils/executablepath_darwin.cpp
deleted file mode 100644
index 2e3c3a0..0000000
--- a/libs/utils/executablepath_darwin.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/executablepath.h>
-#import <Carbon/Carbon.h>
-#include <unistd.h>
-
-void executablepath(char s[PATH_MAX])
-{
- ProcessSerialNumber psn;
- GetCurrentProcess(&psn);
- CFDictionaryRef dict;
- dict = ProcessInformationCopyDictionary(&psn, 0xffffffff);
- CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict,
- CFSTR("CFBundleExecutable"));
- CFStringGetCString(value, s, PATH_MAX+1, kCFStringEncodingUTF8);
-}
-
diff --git a/libs/utils/executablepath_linux.cpp b/libs/utils/executablepath_linux.cpp
deleted file mode 100644
index b8d2a3d..0000000
--- a/libs/utils/executablepath_linux.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/executablepath.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <limits.h>
-#include <stdio.h>
-
-void executablepath(char exe[PATH_MAX])
-{
- char proc[100];
- sprintf(proc, "/proc/%d/exe", getpid());
-
- int err = readlink(proc, exe, PATH_MAX);
-}
-
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 64d1ba2..5bded50 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -588,6 +588,12 @@
}
+ private void enforceMulticastChangePermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
+ "WifiService");
+ }
+
/**
* see {@link WifiManager#getWifiState()}
* @return One of {@link WifiManager#WIFI_STATE_DISABLED},
@@ -1935,8 +1941,8 @@
}
}
- public void enableMulticast(IBinder binder, String tag) {
- enforceChangePermission();
+ public void acquireMulticastLock(IBinder binder, String tag) {
+ enforceMulticastChangePermission();
synchronized (mMulticasters) {
mMulticastEnabled++;
@@ -1958,8 +1964,8 @@
}
}
- public void disableMulticast() {
- enforceChangePermission();
+ public void releaseMulticastLock() {
+ enforceMulticastChangePermission();
int uid = Binder.getCallingUid();
synchronized (mMulticasters) {
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0db868e..c31577c 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -72,8 +72,8 @@
boolean isMulticastEnabled();
- void enableMulticast(IBinder binder, String tag);
+ void acquireMulticastLock(IBinder binder, String tag);
- void disableMulticast();
+ void releaseMulticastLock();
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 141d53f..c4dff6a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -825,6 +825,117 @@
return new WifiLock(WIFI_MODE_FULL, tag);
}
+
+ /**
+ * Create a new MulticastLock
+ *
+ * @param tag a tag for the MulticastLock to identify it in debugging
+ * messages.
+ *
+ * @return a new, unacquired MulticastLock with the given tag.
+ *
+ * @see MulticastLock
+ */
+ public MulticastLock createMulticastLock(String tag) {
+ return new MulticastLock(tag);
+ }
+
+ /**
+ * Allows an application to receive Wifi Multicast packets.
+ * Normally the Wifi stack filters out packets not explicitly
+ * addressed to this device. Acquring a MulticastLock will
+ * cause the stack to receive packets addressed to multicast
+ * addresses. Processing these extra packets can cause a noticable
+ * battery drain and should be disabled when not needed
+ */
+ public class MulticastLock {
+ private String mTag;
+ private final IBinder mBinder;
+ private boolean mHeld;
+
+ private MulticastLock(String tag) {
+ mTag = tag;
+ mBinder = new Binder();
+ mHeld = false;
+ }
+
+ /**
+ * Locks Wifi Multicast on until {@link #release} is called.
+ *
+ * The first call to {@code acquire} will lock the Multicast on
+ * but subsequent calls will be ignored. Only one call to
+ * {@link #release} will be required, regardless of the number of
+ * times that {@code acquire} is called.
+ *
+ * Note that other applications may also lock Wifi Multicast on.
+ * Only they can relinquish their lock.
+ *
+ * Also note that applications cannot leave Multicast locked on.
+ * When an app exits or crashes, any Multicast locks will be released.
+ */
+ public void acquire() {
+ synchronized (mBinder) {
+ if (!mHeld) {
+ try {
+ mService.acquireMulticastLock(mBinder, mTag);
+ mHeld = true;
+ } catch (RemoteException ignore) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Unlocks Wifi Multicast, restoring the filter of packets
+ * not addressed specifically to this device and saving power.
+ *
+ * Note that if any other Wifi Multicast Locks are still outstanding
+ * this {@code release} call will not have an immediate effect. Only
+ * when all applications have released all their Multicast Locks will
+ * the Multicast filter be turned back on.
+ *
+ * Also note that when an app exits or crashes all of its Multicast
+ * Locks will be automatically released.
+ */
+ public void release() {
+ synchronized (mBinder) {
+ if (mHeld) {
+ try {
+ mService.releaseMulticastLock();
+ mHeld = false;
+ } catch (RemoteException ignore) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks whether this MulticastLock is currently held.
+ *
+ * @return true if this MulticastLock is held, false otherwise
+ */
+ public boolean isHeld() {
+ synchronized (mBinder) {
+ return mHeld;
+ }
+ }
+
+ public String toString() {
+ String s1, s2;
+ synchronized (mBinder) {
+ s1 = Integer.toHexString(System.identityHashCode(this));
+ s2 = mHeld ? "held; " : "";
+ return "MulticastLock{ " + s1 + "; " + s2 + " }";
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ release();
+ }
+ }
+
/**
* Check multicast filter status.
*
@@ -839,50 +950,4 @@
return false;
}
}
-
- /**
- * Turn on the reception of multicast packets.
- * The default behavior is to disable multicast packets as they
- * have a noticable negative effect on battery life. An
- * application can turn them on, but should not leave it on for longer
- * than needed. When the app quits (or crashes) its request will
- * be reverted.
- *
- * @param tag a string associated with this request for debugging.
- *
- * @return true on success
- *
- * @see #disableMulticast
- *
- * @hide pending API council approval
- */
- public boolean enableMulticast(String tag) {
- try {
- mService.enableMulticast(new Binder(), tag);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /**
- * Return to the default multicast-off setting.
- * Note that if others had turned on Multicast reception, your
- * call will not turn it back off - they must also turn off their
- * request for multicast reception.
- *
- * @return true on success
- *
- * @see #enableMulticast
- *
- * @hide pending API council approval
- */
- public boolean disableMulticast() {
- try {
- mService.disableMulticast();
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 7ba124fd..e6f4130 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -755,8 +755,10 @@
* first and then off.. if nobody else wants it on it'll be
* off then and it's all synchronized within the API.
*/
- mWM.enableMulticast("WifiStateTracker");
- mWM.disableMulticast();
+ WifiManager.MulticastLock l =
+ mWM.createMulticastLock("WifiStateTracker");
+ l.acquire();
+ l.release();
if (mBluetoothA2dp == null) {
mBluetoothA2dp = new BluetoothA2dp(mContext);