Merge branch 'eclair' into eclair-release
This commit is contained in:
@@ -25618,7 +25618,7 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="listenUsingRfcommOn"
|
||||
<method name="listenUsingRfcomm"
|
||||
return="android.bluetooth.BluetoothServerSocket"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@@ -25628,7 +25628,9 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="channel" type="int">
|
||||
<parameter name="name" type="java.lang.String">
|
||||
</parameter>
|
||||
<parameter name="uuid" type="android.os.ParcelUuid">
|
||||
</parameter>
|
||||
<exception name="IOException" type="java.io.IOException">
|
||||
</exception>
|
||||
@@ -27787,6 +27789,28 @@
|
||||
<parameter name="makeMap" type="boolean">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="isInitialStickyBroadcast"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="isOrderedBroadcast"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="onReceive"
|
||||
return="void"
|
||||
abstract="true"
|
||||
|
||||
@@ -340,7 +340,8 @@ public class Am {
|
||||
private boolean mFinished = false;
|
||||
|
||||
public synchronized void performReceive(
|
||||
Intent intent, int rc, String data, Bundle ext, boolean ord) {
|
||||
Intent intent, int rc, String data, Bundle ext, boolean ord,
|
||||
boolean sticky) {
|
||||
String line = "Broadcast completed: result=" + rc;
|
||||
if (data != null) line = line + ", data=\"" + data + "\"";
|
||||
if (ext != null) line = line + ", extras: " + ext;
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#include <cutils/sockets.h>
|
||||
#include "private/android_filesystem_config.h"
|
||||
|
||||
#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "dumpstate"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "dumpstate.h"
|
||||
|
||||
static char* const gzip_args[] = { "gzip", "-6", 0 };
|
||||
@@ -182,6 +186,8 @@ int main(int argc, char *argv[]) {
|
||||
pid_t pid;
|
||||
gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
|
||||
|
||||
LOGI("begin\n");
|
||||
|
||||
/* set as high priority, and protect from OOM killer */
|
||||
setpriority(PRIO_PROCESS, 0, -20);
|
||||
protect_from_oom_killer();
|
||||
@@ -332,6 +338,8 @@ int main(int argc, char *argv[]) {
|
||||
/* so gzip will terminate */
|
||||
close(STDOUT_FILENO);
|
||||
|
||||
LOGI("done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
|
||||
/**
|
||||
* Object that wraps calls to an {@link IAccountAuthenticatorResponse} object.
|
||||
* TODO: this interface is still in flux
|
||||
* Object used to communicate responses back to the AccountManager
|
||||
*/
|
||||
public class AccountAuthenticatorResponse implements Parcelable {
|
||||
private IAccountAuthenticatorResponse mAccountAuthenticatorResponse;
|
||||
|
||||
@@ -44,8 +44,7 @@ import com.google.android.collect.Maps;
|
||||
/**
|
||||
* A class that helps with interactions with the AccountManagerService. It provides
|
||||
* methods to allow for account, password, and authtoken management for all accounts on the
|
||||
* device. Some of these calls are implemented with the help of the corresponding
|
||||
* {@link IAccountAuthenticator} services. One accesses the {@link AccountManager} by calling:
|
||||
* device. One accesses the {@link AccountManager} by calling:
|
||||
* AccountManager accountManager = AccountManager.get(context);
|
||||
*
|
||||
* <p>
|
||||
|
||||
@@ -653,7 +653,7 @@ public final class ActivityThread {
|
||||
mStrongRef = strong ? rd : null;
|
||||
}
|
||||
public void performReceive(Intent intent, int resultCode,
|
||||
String data, Bundle extras, boolean ordered) {
|
||||
String data, Bundle extras, boolean ordered, boolean sticky) {
|
||||
ReceiverDispatcher rd = mDispatcher.get();
|
||||
if (DEBUG_BROADCAST) {
|
||||
int seq = intent.getIntExtra("seq", -1);
|
||||
@@ -661,7 +661,8 @@ public final class ActivityThread {
|
||||
+ " to " + rd);
|
||||
}
|
||||
if (rd != null) {
|
||||
rd.performReceive(intent, resultCode, data, extras, ordered);
|
||||
rd.performReceive(intent, resultCode, data, extras,
|
||||
ordered, sticky);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -681,6 +682,7 @@ public final class ActivityThread {
|
||||
private String mCurData;
|
||||
private Bundle mCurMap;
|
||||
private boolean mCurOrdered;
|
||||
private boolean mCurSticky;
|
||||
|
||||
public void run() {
|
||||
BroadcastReceiver receiver = mReceiver;
|
||||
@@ -706,6 +708,7 @@ public final class ActivityThread {
|
||||
receiver.setResult(mCurCode, mCurData, mCurMap);
|
||||
receiver.clearAbortBroadcast();
|
||||
receiver.setOrderedHint(mCurOrdered);
|
||||
receiver.setInitialStickyHint(mCurSticky);
|
||||
receiver.onReceive(mContext, intent);
|
||||
} catch (Exception e) {
|
||||
if (mRegistered && mCurOrdered) {
|
||||
@@ -788,7 +791,7 @@ public final class ActivityThread {
|
||||
}
|
||||
|
||||
public void performReceive(Intent intent, int resultCode,
|
||||
String data, Bundle extras, boolean ordered) {
|
||||
String data, Bundle extras, boolean ordered, boolean sticky) {
|
||||
if (DEBUG_BROADCAST) {
|
||||
int seq = intent.getIntExtra("seq", -1);
|
||||
Log.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
|
||||
@@ -800,6 +803,7 @@ public final class ActivityThread {
|
||||
args.mCurData = data;
|
||||
args.mCurMap = extras;
|
||||
args.mCurOrdered = ordered;
|
||||
args.mCurSticky = sticky;
|
||||
if (!mActivityThread.post(args)) {
|
||||
if (mRegistered) {
|
||||
IActivityManager mgr = ActivityManagerNative.getDefault();
|
||||
@@ -1515,9 +1519,9 @@ public final class ActivityThread {
|
||||
// correctly ordered, since these are one-way calls and the binder driver
|
||||
// applies transaction ordering per object for such calls.
|
||||
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
|
||||
int resultCode, String dataStr, Bundle extras, boolean ordered)
|
||||
throws RemoteException {
|
||||
receiver.performReceive(intent, resultCode, dataStr, extras, ordered);
|
||||
int resultCode, String dataStr, Bundle extras, boolean ordered,
|
||||
boolean sticky) throws RemoteException {
|
||||
receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
|
||||
}
|
||||
|
||||
public void scheduleLowMemory() {
|
||||
|
||||
@@ -317,8 +317,9 @@ public abstract class ApplicationThreadNative extends Binder
|
||||
String dataStr = data.readString();
|
||||
Bundle extras = data.readBundle();
|
||||
boolean ordered = data.readInt() != 0;
|
||||
boolean sticky = data.readInt() != 0;
|
||||
scheduleRegisteredReceiver(receiver, intent,
|
||||
resultCode, dataStr, extras, ordered);
|
||||
resultCode, dataStr, extras, ordered, sticky);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -716,7 +717,7 @@ class ApplicationThreadProxy implements IApplicationThread {
|
||||
}
|
||||
|
||||
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
|
||||
int resultCode, String dataStr, Bundle extras, boolean ordered)
|
||||
int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
|
||||
throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
data.writeInterfaceToken(IApplicationThread.descriptor);
|
||||
@@ -726,6 +727,7 @@ class ApplicationThreadProxy implements IApplicationThread {
|
||||
data.writeString(dataStr);
|
||||
data.writeBundle(extras);
|
||||
data.writeInt(ordered ? 1 : 0);
|
||||
data.writeInt(sticky ? 1 : 0);
|
||||
mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
|
||||
IBinder.FLAG_ONEWAY);
|
||||
data.recycle();
|
||||
|
||||
@@ -91,7 +91,7 @@ public interface IApplicationThread extends IInterface {
|
||||
void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)
|
||||
throws RemoteException;
|
||||
void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
|
||||
int resultCode, String data, Bundle extras, boolean ordered)
|
||||
int resultCode, String data, Bundle extras, boolean ordered, boolean sticky)
|
||||
throws RemoteException;
|
||||
void scheduleLowMemory() throws RemoteException;
|
||||
void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
|
||||
|
||||
@@ -147,7 +147,7 @@ public final class PendingIntent implements Parcelable {
|
||||
mHandler = handler;
|
||||
}
|
||||
public void performReceive(Intent intent, int resultCode,
|
||||
String data, Bundle extras, boolean serialized) {
|
||||
String data, Bundle extras, boolean serialized, boolean sticky) {
|
||||
mIntent = intent;
|
||||
mResultCode = resultCode;
|
||||
mResultData = data;
|
||||
|
||||
@@ -18,14 +18,19 @@ package android.bluetooth;
|
||||
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelUuid;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents the local Bluetooth adapter.
|
||||
@@ -40,6 +45,7 @@ import java.util.HashSet;
|
||||
*/
|
||||
public final class BluetoothAdapter {
|
||||
private static final String TAG = "BluetoothAdapter";
|
||||
private static final boolean DBG = true; //STOPSHIP: Remove excess logging
|
||||
|
||||
/**
|
||||
* Sentinel error value for this class. Guaranteed to not equal any other
|
||||
@@ -557,33 +563,142 @@ public final class BluetoothAdapter {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomly picks RFCOMM channels until none are left.
|
||||
* Avoids reserved channels.
|
||||
*/
|
||||
private static class RfcommChannelPicker {
|
||||
private static final int[] RESERVED_RFCOMM_CHANNELS = new int[] {
|
||||
10, // HFAG
|
||||
11, // HSAG
|
||||
12, // OPUSH
|
||||
19, // PBAP
|
||||
};
|
||||
private static LinkedList<Integer> sChannels; // master list of non-reserved channels
|
||||
private static Random sRandom;
|
||||
|
||||
private final LinkedList<Integer> mChannels; // local list of channels left to try
|
||||
|
||||
public RfcommChannelPicker() {
|
||||
synchronized (RfcommChannelPicker.class) {
|
||||
if (sChannels == null) {
|
||||
// lazy initialization of non-reserved rfcomm channels
|
||||
sChannels = new LinkedList<Integer>();
|
||||
for (int i = 1; i <= BluetoothSocket.MAX_RFCOMM_CHANNEL; i++) {
|
||||
sChannels.addLast(new Integer(i));
|
||||
}
|
||||
for (int reserved : RESERVED_RFCOMM_CHANNELS) {
|
||||
sChannels.remove(new Integer(reserved));
|
||||
}
|
||||
sRandom = new Random();
|
||||
}
|
||||
mChannels = (LinkedList<Integer>)sChannels.clone();
|
||||
}
|
||||
}
|
||||
/* Returns next random channel, or -1 if we're out */
|
||||
public int nextChannel() {
|
||||
if (mChannels.size() == 0) {
|
||||
return -1;
|
||||
}
|
||||
return mChannels.remove(sRandom.nextInt(mChannels.size()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a listening, secure RFCOMM Bluetooth socket.
|
||||
* <p>A remote device connecting to this socket will be authenticated and
|
||||
* communication on this socket will be encrypted.
|
||||
* <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
|
||||
* connections to listening {@link BluetoothServerSocket}.
|
||||
* connections from a listening {@link BluetoothServerSocket}.
|
||||
* <p>Valid RFCOMM channels are in range 1 to 30.
|
||||
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
|
||||
* <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
|
||||
* @param channel RFCOMM channel to listen on
|
||||
* @return a listening RFCOMM BluetoothServerSocket
|
||||
* @throws IOException on error, for example Bluetooth not available, or
|
||||
* insufficient permissions, or channel in use.
|
||||
* @hide
|
||||
*/
|
||||
public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
|
||||
BluetoothServerSocket socket = new BluetoothServerSocket(
|
||||
BluetoothSocket.TYPE_RFCOMM, true, true, channel);
|
||||
try {
|
||||
socket.mSocket.bindListen();
|
||||
} catch (IOException e) {
|
||||
int errno = socket.mSocket.bindListen();
|
||||
if (errno != 0) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e2) { }
|
||||
throw e;
|
||||
} catch (IOException e) {}
|
||||
socket.mSocket.throwErrnoNative(errno);
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a listening, secure RFCOMM Bluetooth socket with Service Record.
|
||||
* <p>A remote device connecting to this socket will be authenticated and
|
||||
* communication on this socket will be encrypted.
|
||||
* <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
|
||||
* connections from a listening {@link BluetoothServerSocket}.
|
||||
* <p>The system will assign an unused RFCOMM channel to listen on.
|
||||
* <p>The system will also register a Service Discovery
|
||||
* Protocol (SDP) record with the local SDP server containing the specified
|
||||
* UUID, service name, and auto-assigned channel. Remote Bluetooth devices
|
||||
* can use the same UUID to query our SDP server and discover which channel
|
||||
* to connect to. This SDP record will be removed when this socket is
|
||||
* closed, or if this application closes unexpectedly.
|
||||
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
|
||||
* @param name service name for SDP record
|
||||
* @param uuid uuid for SDP record
|
||||
* @return a listening RFCOMM BluetoothServerSocket
|
||||
* @throws IOException on error, for example Bluetooth not available, or
|
||||
* insufficient permissions, or channel in use.
|
||||
*/
|
||||
public BluetoothServerSocket listenUsingRfcomm(String name, ParcelUuid uuid)
|
||||
throws IOException {
|
||||
RfcommChannelPicker picker = new RfcommChannelPicker();
|
||||
|
||||
BluetoothServerSocket socket;
|
||||
int channel;
|
||||
int errno;
|
||||
while (true) {
|
||||
channel = picker.nextChannel();
|
||||
|
||||
if (channel == -1) {
|
||||
throw new IOException("No available channels");
|
||||
}
|
||||
|
||||
socket = new BluetoothServerSocket(
|
||||
BluetoothSocket.TYPE_RFCOMM, true, true, channel);
|
||||
errno = socket.mSocket.bindListen();
|
||||
if (errno == 0) {
|
||||
if (DBG) Log.d(TAG, "listening on RFCOMM channel " + channel);
|
||||
break; // success
|
||||
} else if (errno == BluetoothSocket.EADDRINUSE) {
|
||||
if (DBG) Log.d(TAG, "RFCOMM channel " + channel + " in use");
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {}
|
||||
continue; // try another channel
|
||||
} else {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {}
|
||||
socket.mSocket.throwErrnoNative(errno); // Exception as a result of bindListen()
|
||||
}
|
||||
}
|
||||
|
||||
int handle = -1;
|
||||
try {
|
||||
handle = mService.addRfcommServiceRecord(name, uuid, channel, new Binder());
|
||||
} catch (RemoteException e) {Log.e(TAG, "", e);}
|
||||
if (handle == -1) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {}
|
||||
throw new IOException("Not able to register SDP record for " + name);
|
||||
}
|
||||
socket.setCloseHandler(mHandler, handle);
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an unencrypted, unauthenticated, RFCOMM server socket.
|
||||
* Call #accept to retrieve connections to this socket.
|
||||
@@ -595,13 +710,12 @@ public final class BluetoothAdapter {
|
||||
public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
|
||||
BluetoothServerSocket socket = new BluetoothServerSocket(
|
||||
BluetoothSocket.TYPE_RFCOMM, false, false, port);
|
||||
try {
|
||||
socket.mSocket.bindListen();
|
||||
} catch (IOException e) {
|
||||
int errno = socket.mSocket.bindListen();
|
||||
if (errno != 0) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e2) { }
|
||||
throw e;
|
||||
} catch (IOException e) {}
|
||||
socket.mSocket.throwErrnoNative(errno);
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
@@ -617,13 +731,12 @@ public final class BluetoothAdapter {
|
||||
public static BluetoothServerSocket listenUsingScoOn() throws IOException {
|
||||
BluetoothServerSocket socket = new BluetoothServerSocket(
|
||||
BluetoothSocket.TYPE_SCO, false, false, -1);
|
||||
try {
|
||||
socket.mSocket.bindListen();
|
||||
} catch (IOException e) {
|
||||
int errno = socket.mSocket.bindListen();
|
||||
if (errno != 0) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e2) { }
|
||||
throw e;
|
||||
} catch (IOException e) {}
|
||||
socket.mSocket.throwErrnoNative(errno);
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
@@ -636,6 +749,17 @@ public final class BluetoothAdapter {
|
||||
return Collections.unmodifiableSet(devices);
|
||||
}
|
||||
|
||||
private Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
/* handle socket closing */
|
||||
int handle = msg.what;
|
||||
try {
|
||||
if (DBG) Log.d(TAG, "Removing service record " + Integer.toHexString(handle));
|
||||
mService.removeServiceRecord(handle);
|
||||
} catch (RemoteException e) {Log.e(TAG, "", e);}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate a Bluetooth address, such as "00:43:A8:23:10:F0"
|
||||
* <p>Alphabetic characters must be uppercase to be valid.
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.bluetooth;
|
||||
|
||||
import android.os.Handler;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -38,7 +40,7 @@ import java.io.IOException;
|
||||
* BluetoothSocket} ready for an outgoing connection to a remote
|
||||
* {@link BluetoothDevice}.
|
||||
*
|
||||
* <p>Use {@link BluetoothAdapter#listenUsingRfcommOn} to create a listening
|
||||
* <p>Use {@link BluetoothAdapter#listenUsingRfcomm} to create a listening
|
||||
* {@link BluetoothServerSocket} ready for incoming connections to the local
|
||||
* {@link BluetoothAdapter}.
|
||||
*
|
||||
@@ -52,6 +54,8 @@ import java.io.IOException;
|
||||
public final class BluetoothServerSocket implements Closeable {
|
||||
|
||||
/*package*/ final BluetoothSocket mSocket;
|
||||
private Handler mHandler;
|
||||
private int mMessage;
|
||||
|
||||
/**
|
||||
* Construct a socket for incoming connections.
|
||||
@@ -101,6 +105,16 @@ public final class BluetoothServerSocket implements Closeable {
|
||||
* throw an IOException.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
synchronized (this) {
|
||||
if (mHandler != null) {
|
||||
mHandler.obtainMessage(mMessage).sendToTarget();
|
||||
}
|
||||
}
|
||||
mSocket.close();
|
||||
}
|
||||
|
||||
/*package*/ synchronized void setCloseHandler(Handler handler, int message) {
|
||||
mHandler = handler;
|
||||
mMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
* BluetoothSocket} ready for an outgoing connection to a remote
|
||||
* {@link BluetoothDevice}.
|
||||
*
|
||||
* <p>Use {@link BluetoothAdapter#listenUsingRfcommOn} to create a listening
|
||||
* <p>Use {@link BluetoothAdapter#listenUsingRfcomm} to create a listening
|
||||
* {@link BluetoothServerSocket} ready for incoming connections to the local
|
||||
* {@link BluetoothAdapter}.
|
||||
*
|
||||
@@ -54,11 +54,17 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
* {@link android.Manifest.permission#BLUETOOTH}
|
||||
*/
|
||||
public final class BluetoothSocket implements Closeable {
|
||||
/** @hide */
|
||||
public static final int MAX_RFCOMM_CHANNEL = 30;
|
||||
|
||||
/** Keep TYPE_ fields in sync with BluetoothSocket.cpp */
|
||||
/*package*/ static final int TYPE_RFCOMM = 1;
|
||||
/*package*/ static final int TYPE_SCO = 2;
|
||||
/*package*/ static final int TYPE_L2CAP = 3;
|
||||
|
||||
/*package*/ static final int EBADFD = 77;
|
||||
/*package*/ static final int EADDRINUSE = 98;
|
||||
|
||||
private final int mType; /* one of TYPE_RFCOMM etc */
|
||||
private final int mPort; /* RFCOMM channel or L2CAP psm */
|
||||
private final BluetoothDevice mDevice; /* remote device */
|
||||
@@ -90,6 +96,11 @@ public final class BluetoothSocket implements Closeable {
|
||||
*/
|
||||
/*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
|
||||
BluetoothDevice device, int port) throws IOException {
|
||||
if (type == BluetoothSocket.TYPE_RFCOMM) {
|
||||
if (port < 1 || port > MAX_RFCOMM_CHANNEL) {
|
||||
throw new IOException("Invalid RFCOMM channel: " + port);
|
||||
}
|
||||
}
|
||||
mType = type;
|
||||
mAuth = auth;
|
||||
mEncrypt = encrypt;
|
||||
@@ -211,11 +222,15 @@ public final class BluetoothSocket implements Closeable {
|
||||
return mOutputStream;
|
||||
}
|
||||
|
||||
/*package*/ void bindListen() throws IOException {
|
||||
/**
|
||||
* Currently returns unix errno instead of throwing IOException,
|
||||
* so that BluetoothAdapter can check the error code for EADDRINUSE
|
||||
*/
|
||||
/*package*/ int bindListen() {
|
||||
mLock.readLock().lock();
|
||||
try {
|
||||
if (mClosed) throw new IOException("socket closed");
|
||||
bindListenNative();
|
||||
if (mClosed) return EBADFD;
|
||||
return bindListenNative();
|
||||
} finally {
|
||||
mLock.readLock().unlock();
|
||||
}
|
||||
@@ -264,11 +279,16 @@ public final class BluetoothSocket implements Closeable {
|
||||
private native void initSocketNative() throws IOException;
|
||||
private native void initSocketFromFdNative(int fd) throws IOException;
|
||||
private native void connectNative() throws IOException;
|
||||
private native void bindListenNative() throws IOException;
|
||||
private native int bindListenNative();
|
||||
private native BluetoothSocket acceptNative(int timeout) throws IOException;
|
||||
private native int availableNative() throws IOException;
|
||||
private native int readNative(byte[] b, int offset, int length) throws IOException;
|
||||
private native int writeNative(byte[] b, int offset, int length) throws IOException;
|
||||
private native void abortNative() throws IOException;
|
||||
private native void destroyNative() throws IOException;
|
||||
/**
|
||||
* Throws an IOException for given posix errno. Done natively so we can
|
||||
* use strerr to convert to string error.
|
||||
*/
|
||||
/*package*/ native void throwErrnoNative(int errno) throws IOException;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ public final class BluetoothUuid {
|
||||
public static final ParcelUuid ObexObjectPush =
|
||||
ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
public static final ParcelUuid[] RESERVED_UUIDS = {
|
||||
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
|
||||
ObexObjectPush};
|
||||
|
||||
public static boolean isAudioSource(ParcelUuid uuid) {
|
||||
return uuid.equals(AudioSource);
|
||||
}
|
||||
|
||||
@@ -63,4 +63,7 @@ interface IBluetooth
|
||||
|
||||
boolean setTrust(in String address, in boolean value);
|
||||
boolean getTrustState(in String address);
|
||||
|
||||
int addRfcommServiceRecord(in String serviceName, in ParcelUuid uuid, int channel, IBinder b);
|
||||
void removeServiceRecord(int handle);
|
||||
}
|
||||
|
||||
@@ -383,6 +383,24 @@ public abstract class BroadcastReceiver {
|
||||
mAbortBroadcast = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the receiver is currently processing an ordered
|
||||
* broadcast.
|
||||
*/
|
||||
public final boolean isOrderedBroadcast() {
|
||||
return mOrderedHint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the receiver is currently processing the initial
|
||||
* value of a sticky broadcast -- that is, the value that was last
|
||||
* broadcast and is currently held in the sticky cache, so this is
|
||||
* not directly the result of a broadcast right now.
|
||||
*/
|
||||
public final boolean isInitialStickyBroadcast() {
|
||||
return mInitialStickyHint;
|
||||
}
|
||||
|
||||
/**
|
||||
* For internal use, sets the hint about whether this BroadcastReceiver is
|
||||
* running in ordered mode.
|
||||
@@ -391,6 +409,14 @@ public abstract class BroadcastReceiver {
|
||||
mOrderedHint = isOrdered;
|
||||
}
|
||||
|
||||
/**
|
||||
* For internal use, sets the hint about whether this BroadcastReceiver is
|
||||
* receiving the initial sticky broadcast value. @hide
|
||||
*/
|
||||
public final void setInitialStickyHint(boolean isInitialSticky) {
|
||||
mInitialStickyHint = isInitialSticky;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control inclusion of debugging help for mismatched
|
||||
* calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter)
|
||||
@@ -414,7 +440,10 @@ public abstract class BroadcastReceiver {
|
||||
}
|
||||
|
||||
void checkSynchronousHint() {
|
||||
if (mOrderedHint) {
|
||||
// Note that we don't assert when receiving the initial sticky value,
|
||||
// since that may have come from an ordered broadcast. We'll catch
|
||||
// them later when the real broadcast happens again.
|
||||
if (mOrderedHint || mInitialStickyHint) {
|
||||
return;
|
||||
}
|
||||
RuntimeException e = new RuntimeException(
|
||||
@@ -429,5 +458,6 @@ public abstract class BroadcastReceiver {
|
||||
private boolean mAbortBroadcast;
|
||||
private boolean mDebugUnregister;
|
||||
private boolean mOrderedHint;
|
||||
private boolean mInitialStickyHint;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,6 @@ import android.os.Bundle;
|
||||
*/
|
||||
oneway interface IIntentReceiver {
|
||||
void performReceive(in Intent intent, int resultCode,
|
||||
String data, in Bundle extras, boolean ordered);
|
||||
String data, in Bundle extras, boolean ordered, boolean sticky);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ public class IntentSender implements Parcelable {
|
||||
mHandler = handler;
|
||||
}
|
||||
public void performReceive(Intent intent, int resultCode,
|
||||
String data, Bundle extras, boolean serialized) {
|
||||
String data, Bundle extras, boolean serialized, boolean sticky) {
|
||||
mIntent = intent;
|
||||
mResultCode = resultCode;
|
||||
mResultData = data;
|
||||
|
||||
@@ -413,6 +413,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
|
||||
}
|
||||
|
||||
private void finish(Result result) {
|
||||
if (isCancelled()) result = null;
|
||||
onPostExecute(result);
|
||||
mStatus = Status.FINISHED;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHeadset;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.bluetooth.BluetoothUuid;
|
||||
import android.bluetooth.IBluetooth;
|
||||
import android.os.ParcelUuid;
|
||||
@@ -37,6 +38,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
@@ -90,6 +92,8 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
private final HashMap <String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache;
|
||||
private final ArrayList <String> mUuidIntentTracker;
|
||||
|
||||
private final HashMap<Integer, Integer> mServiceRecordToPid;
|
||||
|
||||
static {
|
||||
classInitNative();
|
||||
}
|
||||
@@ -117,6 +121,7 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
|
||||
mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>();
|
||||
mUuidIntentTracker = new ArrayList<String>();
|
||||
mServiceRecordToPid = new HashMap<Integer, Integer>();
|
||||
registerForAirplaneMode();
|
||||
}
|
||||
|
||||
@@ -206,6 +211,7 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
|
||||
mIsDiscovering = false;
|
||||
mAdapterProperties.clear();
|
||||
mServiceRecordToPid.clear();
|
||||
|
||||
if (saveSetting) {
|
||||
persistBluetoothOnSetting(false);
|
||||
@@ -1211,6 +1217,71 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
mDeviceServiceChannelCache.put(address, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* b is a handle to a Binder instance, so that this service can be notified
|
||||
* for Applications that terminate unexpectedly, to clean there service
|
||||
* records
|
||||
*/
|
||||
public synchronized int addRfcommServiceRecord(String serviceName, ParcelUuid uuid,
|
||||
int channel, IBinder b) {
|
||||
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
|
||||
"Need BLUETOOTH permission");
|
||||
if (serviceName == null || uuid == null || channel < 1 ||
|
||||
channel > BluetoothSocket.MAX_RFCOMM_CHANNEL) {
|
||||
return -1;
|
||||
}
|
||||
if (BluetoothUuid.isUuidPresent(BluetoothUuid.RESERVED_UUIDS, uuid)) {
|
||||
Log.w(TAG, "Attempted to register a reserved UUID: " + uuid);
|
||||
return -1;
|
||||
}
|
||||
int handle = addRfcommServiceRecordNative(serviceName,
|
||||
uuid.getUuid().getMostSignificantBits(), uuid.getUuid().getLeastSignificantBits(),
|
||||
(short)channel);
|
||||
if (DBG) log("new handle " + Integer.toHexString(handle));
|
||||
if (handle == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pid = Binder.getCallingPid();
|
||||
mServiceRecordToPid.put(new Integer(handle), new Integer(pid));
|
||||
try {
|
||||
b.linkToDeath(new Reaper(handle, pid), 0);
|
||||
} catch (RemoteException e) {}
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void removeServiceRecord(int handle) {
|
||||
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
|
||||
"Need BLUETOOTH permission");
|
||||
checkAndRemoveRecord(handle, Binder.getCallingPid());
|
||||
}
|
||||
|
||||
private synchronized void checkAndRemoveRecord(int handle, int pid) {
|
||||
Integer handleInt = new Integer(handle);
|
||||
Integer owner = mServiceRecordToPid.get(handleInt);
|
||||
if (owner != null && pid == owner.intValue()) {
|
||||
if (DBG) log("Removing service record " + Integer.toHexString(handle) + " for pid " +
|
||||
pid);
|
||||
mServiceRecordToPid.remove(handleInt);
|
||||
removeServiceRecordNative(handle);
|
||||
}
|
||||
}
|
||||
|
||||
private class Reaper implements IBinder.DeathRecipient {
|
||||
int pid;
|
||||
int handle;
|
||||
Reaper(int handle, int pid) {
|
||||
this.pid = pid;
|
||||
this.handle = handle;
|
||||
}
|
||||
public void binderDied() {
|
||||
synchronized (BluetoothService.this) {
|
||||
if (DBG) log("Tracked app " + pid + " died");
|
||||
checkAndRemoveRecord(handle, pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@@ -1263,25 +1334,25 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n");
|
||||
|
||||
switch(mBluetoothState) {
|
||||
case BluetoothAdapter.STATE_OFF:
|
||||
pw.println("\nBluetooth OFF\n");
|
||||
pw.println("Bluetooth OFF\n");
|
||||
return;
|
||||
case BluetoothAdapter.STATE_TURNING_ON:
|
||||
pw.println("\nBluetooth TURNING ON\n");
|
||||
pw.println("Bluetooth TURNING ON\n");
|
||||
return;
|
||||
case BluetoothAdapter.STATE_TURNING_OFF:
|
||||
pw.println("\nBluetooth TURNING OFF\n");
|
||||
pw.println("Bluetooth TURNING OFF\n");
|
||||
return;
|
||||
case BluetoothAdapter.STATE_ON:
|
||||
pw.println("\nBluetooth ON\n");
|
||||
pw.println("Bluetooth ON\n");
|
||||
}
|
||||
|
||||
pw.println("\nLocal address = " + getAddress());
|
||||
pw.println("\nLocal name = " + getName());
|
||||
pw.println("\nisDiscovering() = " + isDiscovering());
|
||||
pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive);
|
||||
|
||||
pw.println("Local address = " + getAddress());
|
||||
pw.println("Local name = " + getName());
|
||||
pw.println("isDiscovering() = " + isDiscovering());
|
||||
|
||||
BluetoothHeadset headset = new BluetoothHeadset(mContext, null);
|
||||
|
||||
@@ -1292,13 +1363,17 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
toBondStateString(bondState),
|
||||
mBondState.getAttempt(address),
|
||||
getRemoteName(address));
|
||||
if (bondState == BluetoothDevice.BOND_BONDED) {
|
||||
ParcelUuid[] uuids = getRemoteUuids(address);
|
||||
if (uuids == null) {
|
||||
pw.printf("\tuuids = null\n");
|
||||
} else {
|
||||
for (ParcelUuid uuid : uuids) {
|
||||
pw.printf("\t" + uuid + "\n");
|
||||
|
||||
Map<ParcelUuid, Integer> uuidChannels = mDeviceServiceChannelCache.get(address);
|
||||
if (uuidChannels == null) {
|
||||
pw.println("\tuuids = null");
|
||||
} else {
|
||||
for (ParcelUuid uuid : uuidChannels.keySet()) {
|
||||
Integer channel = uuidChannels.get(uuid);
|
||||
if (channel == null) {
|
||||
pw.println("\t" + uuid);
|
||||
} else {
|
||||
pw.println("\t" + uuid + " RFCOMM channel = " + channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1310,8 +1385,10 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
devicesObjectPath = value.split(",");
|
||||
}
|
||||
pw.println("\n--ACL connected devices--");
|
||||
for (String device : devicesObjectPath) {
|
||||
pw.println(getAddressFromObjectPath(device));
|
||||
if (devicesObjectPath != null) {
|
||||
for (String device : devicesObjectPath) {
|
||||
pw.println(getAddressFromObjectPath(device));
|
||||
}
|
||||
}
|
||||
|
||||
// Rather not do this from here, but no-where else and I need this
|
||||
@@ -1331,10 +1408,15 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
pw.println("getState() = STATE_ERROR");
|
||||
break;
|
||||
}
|
||||
pw.println("getCurrentHeadset() = " + headset.getCurrentHeadset());
|
||||
pw.println("getBatteryUsageHint() = " + headset.getBatteryUsageHint());
|
||||
|
||||
pw.println("\ngetCurrentHeadset() = " + headset.getCurrentHeadset());
|
||||
pw.println("getBatteryUsageHint() = " + headset.getBatteryUsageHint());
|
||||
headset.close();
|
||||
pw.println("\n--Application Service Records--");
|
||||
for (Integer handle : mServiceRecordToPid.keySet()) {
|
||||
Integer pid = mServiceRecordToPid.get(handle);
|
||||
pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) {
|
||||
@@ -1423,8 +1505,12 @@ public class BluetoothService extends IBluetooth.Stub {
|
||||
private native boolean setPasskeyNative(String address, int passkey, int nativeData);
|
||||
private native boolean setPairingConfirmationNative(String address, boolean confirm,
|
||||
int nativeData);
|
||||
private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value);
|
||||
private native boolean setDevicePropertyBooleanNative(String objectPath, String key,
|
||||
int value);
|
||||
private native boolean createDeviceNative(String address);
|
||||
private native boolean discoverServicesNative(String objectPath, String pattern);
|
||||
|
||||
private native int addRfcommServiceRecordNative(String name, long uuidMsb, long uuidLsb,
|
||||
short channel);
|
||||
private native boolean removeServiceRecordNative(int handle);
|
||||
}
|
||||
|
||||
@@ -237,7 +237,8 @@ static void connectNative(JNIEnv *env, jobject obj) {
|
||||
jniThrowIOException(env, ENOSYS);
|
||||
}
|
||||
|
||||
static void bindListenNative(JNIEnv *env, jobject obj) {
|
||||
/* Returns errno instead of throwing, so java can check errno */
|
||||
static int bindListenNative(JNIEnv *env, jobject obj) {
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
LOGV(__FUNCTION__);
|
||||
|
||||
@@ -248,7 +249,7 @@ static void bindListenNative(JNIEnv *env, jobject obj) {
|
||||
struct asocket *s = get_socketData(env, obj);
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
return EINVAL;
|
||||
|
||||
type = env->GetIntField(obj, field_mType);
|
||||
|
||||
@@ -283,28 +284,25 @@ static void bindListenNative(JNIEnv *env, jobject obj) {
|
||||
memcpy(&addr_l2.l2_bdaddr, &bdaddr, sizeof(bdaddr_t));
|
||||
break;
|
||||
default:
|
||||
jniThrowIOException(env, ENOSYS);
|
||||
return;
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
if (bind(s->fd, addr, addr_sz)) {
|
||||
LOGV("...bind(%d) gave errno %d", s->fd, errno);
|
||||
jniThrowIOException(env, errno);
|
||||
return;
|
||||
return errno;
|
||||
}
|
||||
|
||||
if (listen(s->fd, 1)) {
|
||||
LOGV("...listen(%d) gave errno %d", s->fd, errno);
|
||||
jniThrowIOException(env, errno);
|
||||
return;
|
||||
return errno;
|
||||
}
|
||||
|
||||
LOGV("...bindListenNative(%d) success", s->fd);
|
||||
|
||||
return;
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
jniThrowIOException(env, ENOSYS);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
static jobject acceptNative(JNIEnv *env, jobject obj, int timeout) {
|
||||
@@ -521,17 +519,22 @@ static void destroyNative(JNIEnv *env, jobject obj) {
|
||||
jniThrowIOException(env, ENOSYS);
|
||||
}
|
||||
|
||||
static void throwErrnoNative(JNIEnv *env, jobject obj, jint err) {
|
||||
jniThrowIOException(env, err);
|
||||
}
|
||||
|
||||
static JNINativeMethod sMethods[] = {
|
||||
{"initSocketNative", "()V", (void*) initSocketNative},
|
||||
{"initSocketFromFdNative", "(I)V", (void*) initSocketFromFdNative},
|
||||
{"connectNative", "()V", (void *) connectNative},
|
||||
{"bindListenNative", "()V", (void *) bindListenNative},
|
||||
{"bindListenNative", "()I", (void *) bindListenNative},
|
||||
{"acceptNative", "(I)Landroid/bluetooth/BluetoothSocket;", (void *) acceptNative},
|
||||
{"availableNative", "()I", (void *) availableNative},
|
||||
{"readNative", "([BII)I", (void *) readNative},
|
||||
{"writeNative", "([BII)I", (void *) writeNative},
|
||||
{"abortNative", "()V", (void *) abortNative},
|
||||
{"destroyNative", "()V", (void *) destroyNative},
|
||||
{"throwErrnoNative", "(I)V", (void *) throwErrnoNative},
|
||||
};
|
||||
|
||||
int register_android_bluetooth_BluetoothSocket(JNIEnv *env) {
|
||||
|
||||
@@ -818,6 +818,48 @@ static jboolean discoverServicesNative(JNIEnv *env, jobject object,
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object,
|
||||
jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) {
|
||||
LOGV(__FUNCTION__);
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
native_data_t *nat = get_native_data(env, object);
|
||||
if (nat) {
|
||||
const char *c_name = env->GetStringUTFChars(name, NULL);
|
||||
LOGV("... name = %s", c_name);
|
||||
LOGV("... uuid1 = %llX", uuidMsb);
|
||||
LOGV("... uuid2 = %llX", uuidLsb);
|
||||
LOGV("... channel = %d", channel);
|
||||
DBusMessage *reply = dbus_func_args(env, nat->conn,
|
||||
get_adapter_path(env, object),
|
||||
DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord",
|
||||
DBUS_TYPE_STRING, &c_name,
|
||||
DBUS_TYPE_UINT64, &uuidMsb,
|
||||
DBUS_TYPE_UINT64, &uuidLsb,
|
||||
DBUS_TYPE_UINT16, &channel,
|
||||
DBUS_TYPE_INVALID);
|
||||
env->ReleaseStringUTFChars(name, c_name);
|
||||
return reply ? dbus_returns_uint32(env, reply) : -1;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint handle) {
|
||||
LOGV(__FUNCTION__);
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
native_data_t *nat = get_native_data(env, object);
|
||||
if (nat) {
|
||||
LOGV("... handle = %X", handle);
|
||||
DBusMessage *reply = dbus_func_args(env, nat->conn,
|
||||
get_adapter_path(env, object),
|
||||
DBUS_ADAPTER_IFACE, "RemoveServiceRecord",
|
||||
DBUS_TYPE_UINT32, &handle,
|
||||
DBUS_TYPE_INVALID);
|
||||
return reply ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
#endif
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static JNINativeMethod sMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
@@ -861,6 +903,8 @@ static JNINativeMethod sMethods[] = {
|
||||
(void *)setDevicePropertyBooleanNative},
|
||||
{"createDeviceNative", "(Ljava/lang/String;)Z", (void *)createDeviceNative},
|
||||
{"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative},
|
||||
{"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative},
|
||||
{"removeServiceRecordNative", "(I)Z", (void *)removeServiceRecordNative},
|
||||
};
|
||||
|
||||
int register_android_server_BluetoothService(JNIEnv *env) {
|
||||
|
||||
@@ -8389,7 +8389,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
if (i == 0) {
|
||||
finisher = new IIntentReceiver.Stub() {
|
||||
public void performReceive(Intent intent, int resultCode,
|
||||
String data, Bundle extras, boolean ordered)
|
||||
String data, Bundle extras, boolean ordered,
|
||||
boolean sticky)
|
||||
throws RemoteException {
|
||||
synchronized (ActivityManagerService.this) {
|
||||
mDidUpdate = true;
|
||||
@@ -11571,7 +11572,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
Intent intent = (Intent)allSticky.get(i);
|
||||
BroadcastRecord r = new BroadcastRecord(intent, null,
|
||||
null, -1, -1, null, receivers, null, 0, null, null,
|
||||
false);
|
||||
false, true);
|
||||
if (mParallelBroadcasts.size() == 0) {
|
||||
scheduleBroadcastsLocked();
|
||||
}
|
||||
@@ -11796,7 +11797,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
|
||||
callerPackage, callingPid, callingUid, requiredPermission,
|
||||
registeredReceivers, resultTo, resultCode, resultData, map,
|
||||
ordered);
|
||||
ordered, false);
|
||||
if (DEBUG_BROADCAST) Log.v(
|
||||
TAG, "Enqueueing parallel broadcast " + r
|
||||
+ ": prev had " + mParallelBroadcasts.size());
|
||||
@@ -11875,7 +11876,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
|| resultTo != null) {
|
||||
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
|
||||
callerPackage, callingPid, callingUid, requiredPermission,
|
||||
receivers, resultTo, resultCode, resultData, map, ordered);
|
||||
receivers, resultTo, resultCode, resultData, map, ordered, false);
|
||||
if (DEBUG_BROADCAST) Log.v(
|
||||
TAG, "Enqueueing ordered broadcast " + r
|
||||
+ ": prev had " + mOrderedBroadcasts.size());
|
||||
@@ -12179,15 +12180,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
}
|
||||
|
||||
static void performReceive(ProcessRecord app, IIntentReceiver receiver,
|
||||
Intent intent, int resultCode, String data,
|
||||
Bundle extras, boolean ordered) throws RemoteException {
|
||||
Intent intent, int resultCode, String data, Bundle extras,
|
||||
boolean ordered, boolean sticky) throws RemoteException {
|
||||
if (app != null && app.thread != null) {
|
||||
// If we have an app thread, do the call through that so it is
|
||||
// correctly ordered with other one-way calls.
|
||||
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
|
||||
data, extras, ordered);
|
||||
data, extras, ordered, sticky);
|
||||
} else {
|
||||
receiver.performReceive(intent, resultCode, data, extras, ordered);
|
||||
receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12251,7 +12252,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
}
|
||||
performReceive(filter.receiverList.app, filter.receiverList.receiver,
|
||||
new Intent(r.intent), r.resultCode,
|
||||
r.resultData, r.resultExtras, r.ordered);
|
||||
r.resultData, r.resultExtras, r.ordered, r.sticky);
|
||||
if (ordered) {
|
||||
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
|
||||
}
|
||||
@@ -12384,7 +12385,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
}
|
||||
performReceive(r.callerApp, r.resultTo,
|
||||
new Intent(r.intent), r.resultCode,
|
||||
r.resultData, r.resultExtras, false);
|
||||
r.resultData, r.resultExtras, false, false);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,9 @@ class BroadcastRecord extends Binder {
|
||||
final String callerPackage; // who sent this
|
||||
final int callingPid; // the pid of who sent this
|
||||
final int callingUid; // the uid of who sent this
|
||||
String requiredPermission; // a permission the caller has required
|
||||
final boolean ordered; // serialize the send to receivers?
|
||||
final boolean sticky; // originated from existing sticky data?
|
||||
final String requiredPermission; // a permission the caller has required
|
||||
final List receivers; // contains BroadcastFilter and ResolveInfo
|
||||
final IIntentReceiver resultTo; // who receives final result if non-null
|
||||
long dispatchTime; // when dispatch started on this set of receivers
|
||||
@@ -48,7 +50,6 @@ class BroadcastRecord extends Binder {
|
||||
String resultData; // current result data value.
|
||||
Bundle resultExtras; // current result extra data values.
|
||||
boolean resultAbort; // current result abortBroadcast value.
|
||||
boolean ordered; // serialize the send to receivers?
|
||||
int nextReceiver; // next receiver to be executed.
|
||||
IBinder receiver; // who is currently running, null if none.
|
||||
int state;
|
||||
@@ -86,7 +87,7 @@ class BroadcastRecord extends Binder {
|
||||
+ " resultCode=" + resultCode + " resultData=" + resultData);
|
||||
pw.println(prefix + "resultExtras=" + resultExtras);
|
||||
pw.println(prefix + "resultAbort=" + resultAbort
|
||||
+ " ordered=" + ordered);
|
||||
+ " ordered=" + ordered + " sticky=" + sticky);
|
||||
pw.println(prefix + "nextReceiver=" + nextReceiver
|
||||
+ " receiver=" + receiver);
|
||||
pw.println(prefix + "curFilter=" + curFilter);
|
||||
@@ -122,7 +123,8 @@ class BroadcastRecord extends Binder {
|
||||
BroadcastRecord(Intent _intent, ProcessRecord _callerApp, String _callerPackage,
|
||||
int _callingPid, int _callingUid, String _requiredPermission,
|
||||
List _receivers, IIntentReceiver _resultTo, int _resultCode,
|
||||
String _resultData, Bundle _resultExtras, boolean _serialized) {
|
||||
String _resultData, Bundle _resultExtras, boolean _serialized,
|
||||
boolean _sticky) {
|
||||
intent = _intent;
|
||||
callerApp = _callerApp;
|
||||
callerPackage = _callerPackage;
|
||||
@@ -135,6 +137,7 @@ class BroadcastRecord extends Binder {
|
||||
resultData = _resultData;
|
||||
resultExtras = _resultExtras;
|
||||
ordered = _serialized;
|
||||
sticky = _sticky;
|
||||
nextReceiver = 0;
|
||||
state = IDLE;
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
|
||||
if (sendFinish) {
|
||||
try {
|
||||
finishedReceiver.performReceive(new Intent(finalIntent), 0,
|
||||
null, null, false);
|
||||
null, null, false, false);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ public class CdmaSmsAddress extends SmsAddress {
|
||||
};
|
||||
|
||||
private static final char[] numericCharsSugar = {
|
||||
'(', ')', ' ', '-', '+'
|
||||
'(', ')', ' ', '-', '+', '.'
|
||||
};
|
||||
|
||||
private static final SparseBooleanArray numericCharDialableMap = new SparseBooleanArray (
|
||||
|
||||
@@ -61,6 +61,16 @@ public class CdmaSmsTest extends AndroidTestCase {
|
||||
for (int i = 0; i < data2.length; i++) {
|
||||
assertEquals(addr.origBytes[i], data2[i]);
|
||||
}
|
||||
addr = CdmaSmsAddress.parse("650.253.1000");
|
||||
assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
|
||||
assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
|
||||
assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
|
||||
assertEquals(addr.numberOfDigits, 10);
|
||||
assertEquals(addr.origBytes.length, 10);
|
||||
byte[] data5 = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
|
||||
for (int i = 0; i < data2.length; i++) {
|
||||
assertEquals(addr.origBytes[i], data5[i]);
|
||||
}
|
||||
addr = CdmaSmsAddress.parse("(+886) 917 222 555");
|
||||
assertEquals(addr.ton, CdmaSmsAddress.TON_INTERNATIONAL_OR_IP);
|
||||
assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
|
||||
|
||||
@@ -73,6 +73,48 @@ public class BridgeTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link IStyleResourceValue}.
|
||||
*/
|
||||
private static class StyleResourceValueMock extends ResourceValue
|
||||
implements IStyleResourceValue {
|
||||
|
||||
private String mParentStyle = null;
|
||||
private HashMap<String, IResourceValue> mItems = new HashMap<String, IResourceValue>();
|
||||
|
||||
StyleResourceValueMock(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
StyleResourceValueMock(String name, String parentStyle) {
|
||||
super(name);
|
||||
mParentStyle = parentStyle;
|
||||
}
|
||||
|
||||
public String getParentStyle() {
|
||||
return mParentStyle;
|
||||
}
|
||||
|
||||
public IResourceValue findItem(String name) {
|
||||
return mItems.get(name);
|
||||
}
|
||||
|
||||
public void addItem(IResourceValue value) {
|
||||
mItems.put(value.getName(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceWith(ResourceValue value) {
|
||||
super.replaceWith(value);
|
||||
|
||||
if (value instanceof StyleResourceValueMock) {
|
||||
mItems.clear();
|
||||
mItems.putAll(((StyleResourceValueMock)value).mItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testComputeLayout() throws Exception {
|
||||
|
||||
TestParser parser = new TestParser();
|
||||
@@ -88,8 +130,10 @@ public class BridgeTest extends TestCase {
|
||||
|
||||
// FIXME need a dummy font for the tests!
|
||||
ILayoutResult result = mBridge.computeLayout(parser, new Integer(1) /* projectKey */,
|
||||
screenWidth, screenHeight,
|
||||
"Theme", projectResources, frameworkResources, null, null);
|
||||
screenWidth, screenHeight, false /* full render */,
|
||||
160, 160f, 160f,
|
||||
"Theme", false /* is project theme */,
|
||||
projectResources, frameworkResources, null, null);
|
||||
|
||||
display(result.getRootView(), "");
|
||||
}
|
||||
@@ -191,7 +235,7 @@ public class BridgeTest extends TestCase {
|
||||
* a style item value. If the number of string in the array is not even, an exception is thrown.
|
||||
*/
|
||||
private IStyleResourceValue createStyle(String styleName, String... items) {
|
||||
StyleResourceValue value = new StyleResourceValue(styleName);
|
||||
StyleResourceValueMock value = new StyleResourceValueMock(styleName);
|
||||
|
||||
if (items.length % 3 == 0) {
|
||||
for (int i = 0 ; i < items.length;) {
|
||||
@@ -220,8 +264,10 @@ public class BridgeTest extends TestCase {
|
||||
|
||||
// FIXME need a dummy font for the tests!
|
||||
ILayoutResult result = mBridge.computeLayout(parser, new Integer(1) /* projectKey */,
|
||||
screenWidth, screenHeight,
|
||||
"Theme", projectResources, frameworkResources, null, null);
|
||||
screenWidth, screenHeight, false /* full render */,
|
||||
160, 160f, 160f,
|
||||
"Theme", false /* is project theme */,
|
||||
projectResources, frameworkResources, null, null);
|
||||
|
||||
display(result.getRootView(), "");
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class BridgeXmlBlockParserTest extends TestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
URL url = this.getClass().getClassLoader().getResource("data/layout1.xml");
|
||||
URL url = this.getClass().getClassLoader().getResource("layout1.xml");
|
||||
mXmlPath = url.getFile();
|
||||
mDoc = getXmlDocument(mXmlPath);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ public class NinePatchTest extends TestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
URL url = this.getClass().getClassLoader().getResource("data/button.9.png");
|
||||
URL url = this.getClass().getClassLoader().getResource("button.9.png");
|
||||
|
||||
mPatch = NinePatch.load(url, false /* convert */);
|
||||
}
|
||||
|
||||
@@ -1,60 +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.
|
||||
*/
|
||||
|
||||
package com.android.layoutlib.bridge;
|
||||
|
||||
import com.android.layoutlib.api.IResourceValue;
|
||||
import com.android.layoutlib.api.IStyleResourceValue;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
class StyleResourceValue extends ResourceValue implements IStyleResourceValue {
|
||||
|
||||
private String mParentStyle = null;
|
||||
private HashMap<String, IResourceValue> mItems = new HashMap<String, IResourceValue>();
|
||||
|
||||
StyleResourceValue(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
StyleResourceValue(String name, String parentStyle) {
|
||||
super(name);
|
||||
mParentStyle = parentStyle;
|
||||
}
|
||||
|
||||
public String getParentStyle() {
|
||||
return mParentStyle;
|
||||
}
|
||||
|
||||
public IResourceValue findItem(String name) {
|
||||
return mItems.get(name);
|
||||
}
|
||||
|
||||
public void addItem(IResourceValue value) {
|
||||
mItems.put(value.getName(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceWith(ResourceValue value) {
|
||||
super.replaceWith(value);
|
||||
|
||||
if (value instanceof StyleResourceValue) {
|
||||
mItems.clear();
|
||||
mItems.putAll(((StyleResourceValue)value).mItems);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
@@ -68,6 +68,7 @@ public class AsmGenerator {
|
||||
*
|
||||
* @param log Output logger.
|
||||
* @param osDestJar The path of the destination JAR to create.
|
||||
* @param injectClasses The list of class from layoutlib_create to inject in layoutlib.
|
||||
* @param stubMethods The list of methods to stub out. Each entry must be in the form
|
||||
* "package.package.OuterClass$InnerClass#MethodName".
|
||||
* @param renameClasses The list of classes to rename, must be an even list: the binary FQCN
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.tools.layoutlib.create;
|
||||
|
||||
public class CreateInfo {
|
||||
/**
|
||||
* The list of class from layoutlib_create to inject in layoutlib.
|
||||
*/
|
||||
public final static Class<?>[] INJECTED_CLASSES = new Class<?>[] {
|
||||
OverrideMethod.class,
|
||||
MethodListener.class,
|
||||
MethodAdapter.class,
|
||||
CreateInfo.class
|
||||
};
|
||||
|
||||
/**
|
||||
* The list of methods to stub out. Each entry must be in the form
|
||||
* "package.package.OuterClass$InnerClass#MethodName".
|
||||
*/
|
||||
public final static String[] OVERRIDDEN_METHODS = new String[] {
|
||||
"android.view.View#isInEditMode",
|
||||
"android.content.res.Resources$Theme#obtainStyledAttributes",
|
||||
};
|
||||
|
||||
/**
|
||||
* The list of classes to rename, must be an even list: the binary FQCN
|
||||
* of class to replace followed by the new FQCN.
|
||||
*/
|
||||
public final static String[] RENAMED_CLASSES =
|
||||
new String[] {
|
||||
"android.graphics.Bitmap", "android.graphics._Original_Bitmap",
|
||||
"android.graphics.BitmapShader", "android.graphics._Original_BitmapShader",
|
||||
"android.graphics.Canvas", "android.graphics._Original_Canvas",
|
||||
"android.graphics.ComposeShader", "android.graphics._Original_ComposeShader",
|
||||
"android.graphics.LinearGradient", "android.graphics._Original_LinearGradient",
|
||||
"android.graphics.Matrix", "android.graphics._Original_Matrix",
|
||||
"android.graphics.Paint", "android.graphics._Original_Paint",
|
||||
"android.graphics.Path", "android.graphics._Original_Path",
|
||||
"android.graphics.PorterDuffXfermode", "android.graphics._Original_PorterDuffXfermode",
|
||||
"android.graphics.RadialGradient", "android.graphics._Original_RadialGradient",
|
||||
"android.graphics.Shader", "android.graphics._Original_Shader",
|
||||
"android.graphics.SweepGradient", "android.graphics._Original_SweepGradient",
|
||||
"android.graphics.Typeface", "android.graphics._Original_Typeface",
|
||||
"android.os.ServiceManager", "android.os._Original_ServiceManager",
|
||||
"android.util.FloatMath", "android.util._Original_FloatMath",
|
||||
"android.view.SurfaceView", "android.view._Original_SurfaceView",
|
||||
"android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
|
||||
};
|
||||
|
||||
/**
|
||||
* List of classes for which the methods returning them should be deleted.
|
||||
* The array contains a list of null terminated section starting with the name of the class
|
||||
* to rename in which the methods are deleted, followed by a list of return types identifying
|
||||
* the methods to delete.
|
||||
*/
|
||||
public final static String[] REMOVED_METHODS =
|
||||
new String[] {
|
||||
"android.graphics.Paint", // class to delete methods from
|
||||
"android.graphics.Paint$Align", // list of type identifying methods to delete
|
||||
"android.graphics.Paint$Style",
|
||||
"android.graphics.Paint$Join",
|
||||
"android.graphics.Paint$Cap",
|
||||
"android.graphics.Paint$FontMetrics",
|
||||
"android.graphics.Paint$FontMetricsInt",
|
||||
null }; // separator, for next class/methods list.
|
||||
}
|
||||
|
||||
@@ -43,44 +43,10 @@ public class Main {
|
||||
|
||||
try {
|
||||
AsmGenerator agen = new AsmGenerator(log, osDestJar[0],
|
||||
new Class<?>[] { // classes to inject in the final JAR
|
||||
OverrideMethod.class,
|
||||
MethodListener.class,
|
||||
MethodAdapter.class
|
||||
},
|
||||
new String[] { // methods to force override
|
||||
"android.view.View#isInEditMode",
|
||||
"android.content.res.Resources$Theme#obtainStyledAttributes",
|
||||
},
|
||||
new String[] { // classes to rename (so that we can replace them in layoutlib)
|
||||
// original-platform-class-name ======> renamed-class-name
|
||||
"android.graphics.Bitmap", "android.graphics._Original_Bitmap",
|
||||
"android.graphics.BitmapShader", "android.graphics._Original_BitmapShader",
|
||||
"android.graphics.Canvas", "android.graphics._Original_Canvas",
|
||||
"android.graphics.ComposeShader", "android.graphics._Original_ComposeShader",
|
||||
"android.graphics.LinearGradient", "android.graphics._Original_LinearGradient",
|
||||
"android.graphics.Matrix", "android.graphics._Original_Matrix",
|
||||
"android.graphics.Paint", "android.graphics._Original_Paint",
|
||||
"android.graphics.Path", "android.graphics._Original_Path",
|
||||
"android.graphics.PorterDuffXfermode", "android.graphics._Original_PorterDuffXfermode",
|
||||
"android.graphics.RadialGradient", "android.graphics._Original_RadialGradient",
|
||||
"android.graphics.Shader", "android.graphics._Original_Shader",
|
||||
"android.graphics.SweepGradient", "android.graphics._Original_SweepGradient",
|
||||
"android.graphics.Typeface", "android.graphics._Original_Typeface",
|
||||
"android.os.ServiceManager", "android.os._Original_ServiceManager",
|
||||
"android.util.FloatMath", "android.util._Original_FloatMath",
|
||||
"android.view.SurfaceView", "android.view._Original_SurfaceView",
|
||||
"android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
|
||||
},
|
||||
new String[] { // methods deleted from their return type.
|
||||
"android.graphics.Paint", // class to delete method from
|
||||
"android.graphics.Paint$Align", // list of type identifying methods to delete
|
||||
"android.graphics.Paint$Style",
|
||||
"android.graphics.Paint$Join",
|
||||
"android.graphics.Paint$Cap",
|
||||
"android.graphics.Paint$FontMetrics",
|
||||
"android.graphics.Paint$FontMetricsInt",
|
||||
null }
|
||||
CreateInfo.INJECTED_CLASSES,
|
||||
CreateInfo.OVERRIDDEN_METHODS,
|
||||
CreateInfo.RENAMED_CLASSES,
|
||||
CreateInfo.REMOVED_METHODS
|
||||
);
|
||||
|
||||
AsmAnalyzer aa = new AsmAnalyzer(log, osJarPath, agen,
|
||||
|
||||
Reference in New Issue
Block a user