summaryrefslogtreecommitdiffstats
path: root/core/java/android/server
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
commitd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/server
parent076357b8567458d4b6dfdcf839ef751634cd2bfb (diff)
downloadframeworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/server')
-rw-r--r--core/java/android/server/BluetoothA2dpService.java412
-rw-r--r--core/java/android/server/BluetoothDeviceService.java1107
-rw-r--r--core/java/android/server/BluetoothEventLoop.java373
-rw-r--r--core/java/android/server/data/BuildData.java89
-rw-r--r--core/java/android/server/data/CrashData.java145
-rw-r--r--core/java/android/server/data/StackTraceElementData.java80
-rw-r--r--core/java/android/server/data/ThrowableData.java138
-rwxr-xr-xcore/java/android/server/data/package.html5
-rwxr-xr-xcore/java/android/server/package.html5
-rw-r--r--core/java/android/server/search/SearchManagerService.java156
-rw-r--r--core/java/android/server/search/SearchableInfo.aidl19
-rw-r--r--core/java/android/server/search/SearchableInfo.java850
-rw-r--r--core/java/android/server/search/package.html5
13 files changed, 0 insertions, 3384 deletions
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
deleted file mode 100644
index 58f9491..0000000
--- a/core/java/android/server/BluetoothA2dpService.java
+++ /dev/null
@@ -1,412 +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.
- */
-
-/**
- * TODO: Move this to
- * java/services/com/android/server/BluetoothA2dpService.java
- * and make the contructor package private again.
- * @hide
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothError;
-import android.bluetooth.BluetoothIntent;
-import android.bluetooth.IBluetoothA2dp;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.media.AudioManager;
-import android.os.Binder;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.HashMap;
-import java.util.Iterator;
-
-public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
- private static final String TAG = "BluetoothA2dpService";
- private static final boolean DBG = true;
-
- public static final String BLUETOOTH_A2DP_SERVICE = "bluetooth_a2dp";
-
- private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
- private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
- private static final String A2DP_SINK_ADDRESS = "a2dp_sink_address";
- private static final String BLUETOOTH_ENABLED = "bluetooth_enabled";
-
- private final Context mContext;
- private final IntentFilter mIntentFilter;
- private HashMap<String, SinkState> mAudioDevices;
- private final AudioManager mAudioManager;
-
- private class SinkState {
- public String address;
- public int state;
- public SinkState(String a, int s) {address = a; state = s;}
- }
-
- public BluetoothA2dpService(Context context) {
- mContext = context;
-
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-
- BluetoothDevice device =
- (BluetoothDevice)mContext.getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- throw new RuntimeException("Platform does not support Bluetooth");
- }
-
- if (!initNative()) {
- throw new RuntimeException("Could not init BluetoothA2dpService");
- }
-
- mIntentFilter = new IntentFilter(BluetoothIntent.ENABLED_ACTION);
- mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION);
- mIntentFilter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
- mContext.registerReceiver(mReceiver, mIntentFilter);
-
- if (device.isEnabled()) {
- onBluetoothEnable();
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- cleanupNative();
- } finally {
- super.finalize();
- }
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
- if (action.equals(BluetoothIntent.ENABLED_ACTION)) {
- onBluetoothEnable();
- } else if (action.equals(BluetoothIntent.DISABLED_ACTION)) {
- onBluetoothDisable();
- } else if (action.equals(BluetoothIntent.BOND_STATE_CHANGED_ACTION)) {
- int bondState = intent.getIntExtra(BluetoothIntent.BOND_STATE,
- BluetoothError.ERROR);
- switch(bondState) {
- case BluetoothDevice.BOND_BONDED:
- setSinkPriority(address, BluetoothA2dp.PRIORITY_AUTO);
- break;
- case BluetoothDevice.BOND_BONDING:
- case BluetoothDevice.BOND_NOT_BONDED:
- setSinkPriority(address, BluetoothA2dp.PRIORITY_OFF);
- break;
- }
- }
- }
- };
-
- private synchronized void onBluetoothEnable() {
- mAudioDevices = new HashMap<String, SinkState>();
- String[] paths = (String[])listHeadsetsNative();
- if (paths != null) {
- for (String path : paths) {
- mAudioDevices.put(path, new SinkState(getAddressNative(path),
- isSinkConnectedNative(path) ? BluetoothA2dp.STATE_CONNECTED :
- BluetoothA2dp.STATE_DISCONNECTED));
- }
- }
- mAudioManager.setParameter(BLUETOOTH_ENABLED, "true");
- }
-
- private synchronized void onBluetoothDisable() {
- if (mAudioDevices != null) {
- for (String path : mAudioDevices.keySet()) {
- switch (mAudioDevices.get(path).state) {
- case BluetoothA2dp.STATE_CONNECTING:
- case BluetoothA2dp.STATE_CONNECTED:
- case BluetoothA2dp.STATE_PLAYING:
- disconnectSinkNative(path);
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- break;
- case BluetoothA2dp.STATE_DISCONNECTING:
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- break;
- }
- }
- mAudioDevices = null;
- }
- mAudioManager.setBluetoothA2dpOn(false);
- mAudioManager.setParameter(BLUETOOTH_ENABLED, "false");
- }
-
- public synchronized int connectSink(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (DBG) log("connectSink(" + address + ")");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- if (mAudioDevices == null) {
- return BluetoothError.ERROR;
- }
- String path = lookupPath(address);
- if (path == null) {
- path = createHeadsetNative(address);
- if (DBG) log("new bluez sink: " + address + " (" + path + ")");
- }
- if (path == null) {
- return BluetoothError.ERROR;
- }
-
- SinkState sink = mAudioDevices.get(path);
- int state = BluetoothA2dp.STATE_DISCONNECTED;
- if (sink != null) {
- state = sink.state;
- }
- switch (state) {
- case BluetoothA2dp.STATE_CONNECTED:
- case BluetoothA2dp.STATE_PLAYING:
- case BluetoothA2dp.STATE_DISCONNECTING:
- return BluetoothError.ERROR;
- case BluetoothA2dp.STATE_CONNECTING:
- return BluetoothError.SUCCESS;
- }
-
- // State is DISCONNECTED
- if (!connectSinkNative(path)) {
- return BluetoothError.ERROR;
- }
- updateState(path, BluetoothA2dp.STATE_CONNECTING);
- return BluetoothError.SUCCESS;
- }
-
- public synchronized int disconnectSink(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (DBG) log("disconnectSink(" + address + ")");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- if (mAudioDevices == null) {
- return BluetoothError.ERROR;
- }
- String path = lookupPath(address);
- if (path == null) {
- return BluetoothError.ERROR;
- }
- switch (mAudioDevices.get(path).state) {
- case BluetoothA2dp.STATE_DISCONNECTED:
- return BluetoothError.ERROR;
- case BluetoothA2dp.STATE_DISCONNECTING:
- return BluetoothError.SUCCESS;
- }
-
- // State is CONNECTING or CONNECTED or PLAYING
- if (!disconnectSinkNative(path)) {
- return BluetoothError.ERROR;
- } else {
- updateState(path, BluetoothA2dp.STATE_DISCONNECTING);
- return BluetoothError.SUCCESS;
- }
- }
-
- public synchronized List<String> listConnectedSinks() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- List<String> connectedSinks = new ArrayList<String>();
- if (mAudioDevices == null) {
- return connectedSinks;
- }
- for (SinkState sink : mAudioDevices.values()) {
- if (sink.state == BluetoothA2dp.STATE_CONNECTED ||
- sink.state == BluetoothA2dp.STATE_PLAYING) {
- connectedSinks.add(sink.address);
- }
- }
- return connectedSinks;
- }
-
- public synchronized int getSinkState(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- if (mAudioDevices == null) {
- return BluetoothA2dp.STATE_DISCONNECTED;
- }
- for (SinkState sink : mAudioDevices.values()) {
- if (address.equals(sink.address)) {
- return sink.state;
- }
- }
- return BluetoothA2dp.STATE_DISCONNECTED;
- }
-
- public synchronized int getSinkPriority(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.getBluetoothA2dpSinkPriorityKey(address),
- BluetoothA2dp.PRIORITY_OFF);
- }
-
- public synchronized int setSinkPriority(String address, int priority) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- return Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.getBluetoothA2dpSinkPriorityKey(address), priority) ?
- BluetoothError.SUCCESS : BluetoothError.ERROR;
- }
-
- private synchronized void onHeadsetCreated(String path) {
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- }
-
- private synchronized void onHeadsetRemoved(String path) {
- if (mAudioDevices == null) return;
- mAudioDevices.remove(path);
- }
-
- private synchronized void onSinkConnected(String path) {
- if (mAudioDevices == null) return;
- // bluez 3.36 quietly disconnects the previous sink when a new sink
- // is connected, so we need to mark all previously connected sinks as
- // disconnected
- for (String oldPath : mAudioDevices.keySet()) {
- if (path.equals(oldPath)) {
- continue;
- }
- int state = mAudioDevices.get(oldPath).state;
- if (state == BluetoothA2dp.STATE_CONNECTED || state == BluetoothA2dp.STATE_PLAYING) {
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- }
- }
-
- updateState(path, BluetoothA2dp.STATE_CONNECTING);
- mAudioManager.setParameter(A2DP_SINK_ADDRESS, lookupAddress(path));
- mAudioManager.setBluetoothA2dpOn(true);
- updateState(path, BluetoothA2dp.STATE_CONNECTED);
- }
-
- private synchronized void onSinkDisconnected(String path) {
- mAudioManager.setBluetoothA2dpOn(false);
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- }
-
- private synchronized void onSinkPlaying(String path) {
- updateState(path, BluetoothA2dp.STATE_PLAYING);
- }
-
- private synchronized void onSinkStopped(String path) {
- updateState(path, BluetoothA2dp.STATE_CONNECTED);
- }
-
- private synchronized final String lookupAddress(String path) {
- if (mAudioDevices == null) return null;
- SinkState sink = mAudioDevices.get(path);
- if (sink == null) {
- Log.w(TAG, "lookupAddress() called for unknown device " + path);
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- }
- String address = mAudioDevices.get(path).address;
- if (address == null) Log.e(TAG, "Can't find address for " + path);
- return address;
- }
-
- private synchronized final String lookupPath(String address) {
- if (mAudioDevices == null) return null;
-
- for (String path : mAudioDevices.keySet()) {
- if (address.equals(mAudioDevices.get(path).address)) {
- return path;
- }
- }
- return null;
- }
-
- private synchronized void updateState(String path, int state) {
- if (mAudioDevices == null) return;
-
- SinkState s = mAudioDevices.get(path);
- int prevState;
- String address;
- if (s == null) {
- address = getAddressNative(path);
- mAudioDevices.put(path, new SinkState(address, state));
- prevState = BluetoothA2dp.STATE_DISCONNECTED;
- } else {
- address = lookupAddress(path);
- prevState = s.state;
- s.state = state;
- }
-
- if (state != prevState) {
- if (DBG) log("state " + address + " (" + path + ") " + prevState + "->" + state);
-
- Intent intent = new Intent(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothA2dp.SINK_PREVIOUS_STATE, prevState);
- intent.putExtra(BluetoothA2dp.SINK_STATE, state);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
- if ((prevState == BluetoothA2dp.STATE_CONNECTED ||
- prevState == BluetoothA2dp.STATE_PLAYING) &&
- (state != BluetoothA2dp.STATE_CONNECTED &&
- state != BluetoothA2dp.STATE_PLAYING)) {
- // disconnected
- intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
- mContext.sendBroadcast(intent);
- }
- }
- }
-
- @Override
- protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mAudioDevices == null) return;
- pw.println("Cached audio devices:");
- for (String path : mAudioDevices.keySet()) {
- SinkState sink = mAudioDevices.get(path);
- pw.println(path + " " + sink.address + " " + BluetoothA2dp.stateToString(sink.state));
- }
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-
- private native boolean initNative();
- private native void cleanupNative();
- private synchronized native String[] listHeadsetsNative();
- private synchronized native String createHeadsetNative(String address);
- private synchronized native boolean removeHeadsetNative(String path);
- private synchronized native String getAddressNative(String path);
- private synchronized native boolean connectSinkNative(String path);
- private synchronized native boolean disconnectSinkNative(String path);
- private synchronized native boolean isSinkConnectedNative(String path);
-}
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java
deleted file mode 100644
index fa53a60..0000000
--- a/core/java/android/server/BluetoothDeviceService.java
+++ /dev/null
@@ -1,1107 +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.
- */
-
-/**
- * TODO: Move this to
- * java/services/com/android/server/BluetoothDeviceService.java
- * and make the contructor package private again.
- *
- * @hide
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothError;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothIntent;
-import android.bluetooth.IBluetoothDevice;
-import android.bluetooth.IBluetoothDeviceCallback;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.SystemService;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-public class BluetoothDeviceService extends IBluetoothDevice.Stub {
- private static final String TAG = "BluetoothDeviceService";
- private static final boolean DBG = true;
-
- private int mNativeData;
- private BluetoothEventLoop mEventLoop;
- private IntentFilter mIntentFilter;
- private boolean mIsAirplaneSensitive;
- private final BondState mBondState = new BondState(); // local cache of bondings
- private volatile boolean mIsEnabled; // local cache of isEnabledNative()
- private boolean mIsDiscovering;
-
- private final Context mContext;
-
- private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
- private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
- static {
- classInitNative();
- }
- private native static void classInitNative();
-
- public BluetoothDeviceService(Context context) {
- mContext = context;
- }
-
- /** Must be called after construction, and before any other method.
- */
- public synchronized void init() {
- initializeNativeDataNative();
- mIsEnabled = (isEnabledNative() == 1);
- if (mIsEnabled) {
- mBondState.loadBondState();
- }
- mIsDiscovering = false;
- mEventLoop = new BluetoothEventLoop(mContext, this);
- registerForAirplaneMode();
- }
- private native void initializeNativeDataNative();
-
- @Override
- protected void finalize() throws Throwable {
- if (mIsAirplaneSensitive) {
- mContext.unregisterReceiver(mReceiver);
- }
- try {
- cleanupNativeDataNative();
- } finally {
- super.finalize();
- }
- }
- private native void cleanupNativeDataNative();
-
- public boolean isEnabled() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mIsEnabled;
- }
- private native int isEnabledNative();
-
- /**
- * Bring down bluetooth and disable BT in settings. Returns true on success.
- */
- public boolean disable() {
- return disable(true);
- }
-
- /**
- * Bring down bluetooth. Returns true on success.
- *
- * @param saveSetting If true, disable BT in settings
- *
- */
- public synchronized boolean disable(boolean saveSetting) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
-
- if (mEnableThread != null && mEnableThread.isAlive()) {
- return false;
- }
- if (!mIsEnabled) {
- return true;
- }
- mEventLoop.stop();
- disableNative();
-
- // mark in progress bondings as cancelled
- for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
- mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED,
- BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
- }
- // update mode
- Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
- mIsEnabled = false;
- if (saveSetting) {
- persistBluetoothOnSetting(false);
- }
- mIsDiscovering = false;
- intent = new Intent(BluetoothIntent.DISABLED_ACTION);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- return true;
- }
-
- /**
- * Bring up bluetooth, asynchronously, and enable BT in settings.
- * This turns on/off the underlying hardware.
- *
- * @return True on success (so far), guaranteeing the callback with be
- * notified when complete.
- */
- public boolean enable(IBluetoothDeviceCallback callback) {
- return enable(callback, true);
- }
-
- /**
- * Enable this Bluetooth device, asynchronously.
- * This turns on/off the underlying hardware.
- *
- * @param saveSetting If true, enable BT in settings
- *
- * @return True on success (so far), guaranteeing the callback with be
- * notified when complete.
- */
- public synchronized boolean enable(IBluetoothDeviceCallback callback,
- boolean saveSetting) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
-
- // Airplane mode can prevent Bluetooth radio from being turned on.
- if (mIsAirplaneSensitive && isAirplaneModeOn()) {
- return false;
- }
- if (mIsEnabled) {
- return false;
- }
- if (mEnableThread != null && mEnableThread.isAlive()) {
- return false;
- }
- mEnableThread = new EnableThread(callback, saveSetting);
- mEnableThread.start();
- return true;
- }
-
- private static final int REGISTER_SDP_RECORDS = 1;
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case REGISTER_SDP_RECORDS:
- //TODO: Don't assume HSP/HFP is running, don't use sdptool,
- if (isEnabled()) {
- SystemService.start("hsag");
- SystemService.start("hfag");
- }
- }
- }
- };
-
- private EnableThread mEnableThread;
-
- private class EnableThread extends Thread {
- private final IBluetoothDeviceCallback mEnableCallback;
- private final boolean mSaveSetting;
- public EnableThread(IBluetoothDeviceCallback callback, boolean saveSetting) {
- mEnableCallback = callback;
- mSaveSetting = saveSetting;
- }
- public void run() {
- boolean res = (enableNative() == 0);
- if (res) {
- mEventLoop.start();
- }
-
- if (mEnableCallback != null) {
- try {
- mEnableCallback.onEnableResult(res ?
- BluetoothDevice.RESULT_SUCCESS :
- BluetoothDevice.RESULT_FAILURE);
- } catch (RemoteException e) {}
- }
-
- if (res) {
- mIsEnabled = true;
- if (mSaveSetting) {
- persistBluetoothOnSetting(true);
- }
- mIsDiscovering = false;
- Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION);
- mBondState.loadBondState();
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000);
-
- // Update mode
- mEventLoop.onModeChanged(getModeNative());
- }
- mEnableThread = null;
- }
- }
-
- private void persistBluetoothOnSetting(boolean bluetoothOn) {
- long origCallerIdentityToken = Binder.clearCallingIdentity();
- Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
- bluetoothOn ? 1 : 0);
- Binder.restoreCallingIdentity(origCallerIdentityToken);
- }
-
- private native int enableNative();
- private native int disableNative();
-
- /* package */ BondState getBondState() {
- return mBondState;
- }
-
- /** local cache of bonding state.
- /* we keep our own state to track the intermediate state BONDING, which
- /* bluez does not track.
- * All addreses must be passed in upper case.
- */
- public class BondState {
- private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
- private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();
- private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>();
- // List of all the vendor_id prefix of Bluetooth addresses for which
- // auto pairing is not attempted
- private final ArrayList<String> mAutoPairingBlacklisted =
- new ArrayList<String>(Arrays.asList(
- "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS
- "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS
- "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57"// Murata for Prius 2007
- ));
-
- public synchronized void loadBondState() {
- if (!mIsEnabled) {
- return;
- }
- String[] bonds = listBondingsNative();
- if (bonds == null) {
- return;
- }
- mState.clear();
- if (DBG) log("found " + bonds.length + " bonded devices");
- for (String address : bonds) {
- mState.put(address.toUpperCase(), BluetoothDevice.BOND_BONDED);
- }
- }
-
- public synchronized void setBondState(String address, int state) {
- setBondState(address, state, 0);
- }
-
- /** reason is ignored unless state == BOND_NOT_BONDED */
- public synchronized void setBondState(String address, int state, int reason) {
- int oldState = getBondState(address);
- if (oldState == state) {
- return;
- }
- if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" +
- reason + ")");
- Intent intent = new Intent(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.BOND_STATE, state);
- intent.putExtra(BluetoothIntent.BOND_PREVIOUS_STATE, oldState);
- if (state == BluetoothDevice.BOND_NOT_BONDED) {
- if (reason <= 0) {
- Log.w(TAG, "setBondState() called to unbond device, but reason code is " +
- "invalid. Overriding reason code with BOND_RESULT_REMOVED");
- reason = BluetoothDevice.UNBOND_REASON_REMOVED;
- }
- intent.putExtra(BluetoothIntent.REASON, reason);
- mState.remove(address);
- } else {
- mState.put(address, state);
- }
-
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
- public boolean isAutoPairingBlacklisted(String address) {
- for (String blacklistAddress : mAutoPairingBlacklisted) {
- if (address.startsWith(blacklistAddress)) return true;
- }
- return false;
- }
-
- public synchronized int getBondState(String address) {
- Integer state = mState.get(address);
- if (state == null) {
- return BluetoothDevice.BOND_NOT_BONDED;
- }
- return state.intValue();
- }
-
- private synchronized String[] listInState(int state) {
- ArrayList<String> result = new ArrayList<String>(mState.size());
- for (Map.Entry<String, Integer> e : mState.entrySet()) {
- if (e.getValue().intValue() == state) {
- result.add(e.getKey());
- }
- }
- return result.toArray(new String[result.size()]);
- }
-
- public synchronized void addAutoPairingFailure(String address) {
- if (!mAutoPairingFailures.contains(address)) {
- mAutoPairingFailures.add(address);
- }
- }
-
- public synchronized boolean isAutoPairingAttemptsInProgress(String address) {
- return getAttempt(address) != 0;
- }
-
- public synchronized void clearPinAttempts(String address) {
- mPinAttempt.remove(address);
- }
-
- public synchronized boolean hasAutoPairingFailed(String address) {
- return mAutoPairingFailures.contains(address);
- }
-
- public synchronized int getAttempt(String address) {
- Integer attempt = mPinAttempt.get(address);
- if (attempt == null) {
- return 0;
- }
- return attempt.intValue();
- }
-
- public synchronized void attempt(String address) {
- Integer attempt = mPinAttempt.get(address);
- int newAttempt;
- if (attempt == null) {
- newAttempt = 1;
- } else {
- newAttempt = attempt.intValue() + 1;
- }
- mPinAttempt.put(address, new Integer(newAttempt));
- }
-
- }
- private native String[] listBondingsNative();
-
- private static String toBondStateString(int bondState) {
- switch (bondState) {
- case BluetoothDevice.BOND_NOT_BONDED:
- return "not bonded";
- case BluetoothDevice.BOND_BONDING:
- return "bonding";
- case BluetoothDevice.BOND_BONDED:
- return "bonded";
- default:
- return "??????";
- }
- }
-
- public synchronized String getAddress() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getAddressNative();
- }
- private native String getAddressNative();
-
- public synchronized String getName() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getNameNative();
- }
- private native String getNameNative();
-
- public synchronized boolean setName(String name) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (name == null) {
- return false;
- }
- // hcid handles persistance of the bluetooth name
- return setNameNative(name);
- }
- private native boolean setNameNative(String name);
-
- /**
- * Returns the user-friendly name of a remote device. This value is
- * retrned from our local cache, which is updated during device discovery.
- * Do not expect to retrieve the updated remote name immediately after
- * changing the name on the remote device.
- *
- * @param address Bluetooth address of remote device.
- *
- * @return The user-friendly name of the specified remote device.
- */
- public synchronized String getRemoteName(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteNameNative(address);
- }
- private native String getRemoteNameNative(String address);
-
- /* pacakge */ native String getAdapterPathNative();
-
- public synchronized boolean startDiscovery(boolean resolveNames) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return startDiscoveryNative(resolveNames);
- }
- private native boolean startDiscoveryNative(boolean resolveNames);
-
- public synchronized boolean cancelDiscovery() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return cancelDiscoveryNative();
- }
- private native boolean cancelDiscoveryNative();
-
- public synchronized boolean isDiscovering() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mIsDiscovering;
- }
-
- /* package */ void setIsDiscovering(boolean isDiscovering) {
- mIsDiscovering = isDiscovering;
- }
-
- public synchronized boolean startPeriodicDiscovery() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return startPeriodicDiscoveryNative();
- }
- private native boolean startPeriodicDiscoveryNative();
-
- public synchronized boolean stopPeriodicDiscovery() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return stopPeriodicDiscoveryNative();
- }
- private native boolean stopPeriodicDiscoveryNative();
-
- public synchronized boolean isPeriodicDiscovery() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return isPeriodicDiscoveryNative();
- }
- private native boolean isPeriodicDiscoveryNative();
-
- /**
- * Set the discoverability window for the device. A timeout of zero
- * makes the device permanently discoverable (if the device is
- * discoverable). Setting the timeout to a nonzero value does not make
- * a device discoverable; you need to call setMode() to make the device
- * explicitly discoverable.
- *
- * @param timeout_s The discoverable timeout in seconds.
- */
- public synchronized boolean setDiscoverableTimeout(int timeout) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return setDiscoverableTimeoutNative(timeout);
- }
- private native boolean setDiscoverableTimeoutNative(int timeout_s);
-
- /**
- * Get the discoverability window for the device. A timeout of zero
- * means that the device is permanently discoverable (if the device is
- * in the discoverable mode).
- *
- * @return The discoverability window of the device, in seconds. A negative
- * value indicates an error.
- */
- public synchronized int getDiscoverableTimeout() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getDiscoverableTimeoutNative();
- }
- private native int getDiscoverableTimeoutNative();
-
- public synchronized boolean isAclConnected(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- return isConnectedNative(address);
- }
- private native boolean isConnectedNative(String address);
-
- public synchronized int getScanMode() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return bluezStringToScanMode(getModeNative());
- }
- private native String getModeNative();
-
- public synchronized boolean setScanMode(int mode) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- String bluezMode = scanModeToBluezString(mode);
- if (bluezMode != null) {
- return setModeNative(bluezMode);
- }
- return false;
- }
- private native boolean setModeNative(String mode);
-
- public synchronized boolean disconnectRemoteDeviceAcl(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- return disconnectRemoteDeviceNative(address);
- }
- private native boolean disconnectRemoteDeviceNative(String address);
-
- public synchronized boolean createBond(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- address = address.toUpperCase();
-
- // Check for bond state only if we are not performing auto
- // pairing exponential back-off attempts.
- if (!mBondState.isAutoPairingAttemptsInProgress(address) &&
- mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) {
- return false;
- }
-
- if (!createBondingNative(address, 60000 /* 1 minute */)) {
- return false;
- }
-
- mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
- return true;
- }
- private native boolean createBondingNative(String address, int timeout_ms);
-
- public synchronized boolean cancelBondProcess(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- address = address.toUpperCase();
- if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) {
- return false;
- }
-
- mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED,
- BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
- cancelBondingProcessNative(address);
- return true;
- }
- private native boolean cancelBondingProcessNative(String address);
-
- public synchronized boolean removeBond(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- return removeBondingNative(address);
- }
- private native boolean removeBondingNative(String address);
-
- public synchronized String[] listBonds() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBondState.listInState(BluetoothDevice.BOND_BONDED);
- }
-
- public synchronized int getBondState(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- return mBondState.getBondState(address.toUpperCase());
- }
-
- public synchronized String[] listAclConnections() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return listConnectionsNative();
- }
- private native String[] listConnectionsNative();
-
- /**
- * This method lists all remote devices that this adapter is aware of.
- * This is a list not only of all most-recently discovered devices, but of
- * all devices discovered by this adapter up to some point in the past.
- * Note that many of these devices may not be in the neighborhood anymore,
- * and attempting to connect to them will result in an error.
- *
- * @return An array of strings representing the Bluetooth addresses of all
- * remote devices that this adapter is aware of.
- */
- public synchronized String[] listRemoteDevices() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return listRemoteDevicesNative();
- }
- private native String[] listRemoteDevicesNative();
-
- /**
- * Returns the version of the Bluetooth chip. This version is compiled from
- * the LMP version. In case of EDR the features attribute must be checked.
- * Example: "Bluetooth 2.0 + EDR".
- *
- * @return a String representation of the this Adapter's underlying
- * Bluetooth-chip version.
- */
- public synchronized String getVersion() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getVersionNative();
- }
- private native String getVersionNative();
-
- /**
- * Returns the revision of the Bluetooth chip. This is a vendor-specific
- * value and in most cases it represents the firmware version. This might
- * derive from the HCI revision and LMP subversion values or via extra
- * vendord specific commands.
- * In case the revision of a chip is not available. This method should
- * return the LMP subversion value as a string.
- * Example: "HCI 19.2"
- *
- * @return The HCI revision of this adapter.
- */
- public synchronized String getRevision() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getRevisionNative();
- }
- private native String getRevisionNative();
-
- /**
- * Returns the manufacturer of the Bluetooth chip. If the company id is not
- * known the sting "Company ID %d" where %d should be replaced with the
- * numeric value from the manufacturer field.
- * Example: "Cambridge Silicon Radio"
- *
- * @return Manufacturer name.
- */
- public synchronized String getManufacturer() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getManufacturerNative();
- }
- private native String getManufacturerNative();
-
- /**
- * Returns the company name from the OUI database of the Bluetooth device
- * address. This function will need a valid and up-to-date oui.txt from
- * the IEEE. This value will be different from the manufacturer string in
- * the most cases.
- * If the oui.txt file is not present or the OUI part of the Bluetooth
- * address is not listed, it should return the string "OUI %s" where %s is
- * the actual OUI.
- *
- * Example: "Apple Computer"
- *
- * @return company name
- */
- public synchronized String getCompany() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getCompanyNative();
- }
- private native String getCompanyNative();
-
- /**
- * Like getVersion(), but for a remote device.
- *
- * @param address The Bluetooth address of the remote device.
- *
- * @return remote-device Bluetooth version
- *
- * @see #getVersion
- */
- public synchronized String getRemoteVersion(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteVersionNative(address);
- }
- private native String getRemoteVersionNative(String address);
-
- /**
- * Like getRevision(), but for a remote device.
- *
- * @param address The Bluetooth address of the remote device.
- *
- * @return remote-device HCI revision
- *
- * @see #getRevision
- */
- public synchronized String getRemoteRevision(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteRevisionNative(address);
- }
- private native String getRemoteRevisionNative(String address);
-
- /**
- * Like getManufacturer(), but for a remote device.
- *
- * @param address The Bluetooth address of the remote device.
- *
- * @return remote-device Bluetooth chip manufacturer
- *
- * @see #getManufacturer
- */
- public synchronized String getRemoteManufacturer(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteManufacturerNative(address);
- }
- private native String getRemoteManufacturerNative(String address);
-
- /**
- * Like getCompany(), but for a remote device.
- *
- * @param address The Bluetooth address of the remote device.
- *
- * @return remote-device company
- *
- * @see #getCompany
- */
- public synchronized String getRemoteCompany(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteCompanyNative(address);
- }
- private native String getRemoteCompanyNative(String address);
-
- /**
- * Returns the date and time when the specified remote device has been seen
- * by a discover procedure.
- * Example: "2006-02-08 12:00:00 GMT"
- *
- * @return a String with the timestamp.
- */
- public synchronized String lastSeen(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return lastSeenNative(address);
- }
- private native String lastSeenNative(String address);
-
- /**
- * Returns the date and time when the specified remote device has last been
- * connected to
- * Example: "2006-02-08 12:00:00 GMT"
- *
- * @return a String with the timestamp.
- */
- public synchronized String lastUsed(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return lastUsedNative(address);
- }
- private native String lastUsedNative(String address);
-
- /**
- * Gets the remote major, minor, and service classes encoded as a 32-bit
- * integer.
- *
- * Note: this value is retrieved from cache, because we get it during
- * remote-device discovery.
- *
- * @return 32-bit integer encoding the remote major, minor, and service
- * classes.
- *
- * @see #getRemoteMajorClass
- * @see #getRemoteMinorClass
- * @see #getRemoteServiceClasses
- */
- public synchronized int getRemoteClass(String address) {
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return -1;
- }
- return getRemoteClassNative(address);
- }
- private native int getRemoteClassNative(String address);
-
- /**
- * Gets the remote features encoded as bit mask.
- *
- * Note: This method may be obsoleted soon.
- *
- * @return byte array of features.
- */
- public synchronized byte[] getRemoteFeatures(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteFeaturesNative(address);
- }
- private native byte[] getRemoteFeaturesNative(String address);
-
- /**
- * This method and {@link #getRemoteServiceRecord} query the SDP service
- * on a remote device. They do not interpret the data, but simply return
- * it raw to the user. To read more about SDP service handles and records,
- * consult the Bluetooth core documentation (www.bluetooth.com).
- *
- * @param address Bluetooth address of remote device.
- * @param match a String match to narrow down the service-handle search.
- * The only supported value currently is "hsp" for the headset
- * profile. To retrieve all service handles, simply pass an empty
- * match string.
- *
- * @return all service handles corresponding to the string match.
- *
- * @see #getRemoteServiceRecord
- */
- public synchronized int[] getRemoteServiceHandles(String address, String match) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- if (match == null) {
- match = "";
- }
- return getRemoteServiceHandlesNative(address, match);
- }
- private native int[] getRemoteServiceHandlesNative(String address, String match);
-
- /**
- * This method retrieves the service records corresponding to a given
- * service handle (method {@link #getRemoteServiceHandles} retrieves the
- * service handles.)
- *
- * This method and {@link #getRemoteServiceHandles} do not interpret their
- * data, but simply return it raw to the user. To read more about SDP
- * service handles and records, consult the Bluetooth core documentation
- * (www.bluetooth.com).
- *
- * @param address Bluetooth address of remote device.
- * @param handle Service handle returned by {@link #getRemoteServiceHandles}
- *
- * @return a byte array of all service records corresponding to the
- * specified service handle.
- *
- * @see #getRemoteServiceHandles
- */
- public synchronized byte[] getRemoteServiceRecord(String address, int handle) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteServiceRecordNative(address, handle);
- }
- private native byte[] getRemoteServiceRecordNative(String address, int handle);
-
- private static final int MAX_OUTSTANDING_ASYNC = 32;
-
- // AIDL does not yet support short's
- public synchronized boolean getRemoteServiceChannel(String address, int uuid16,
- IBluetoothDeviceCallback callback) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- HashMap<String, IBluetoothDeviceCallback> callbacks =
- mEventLoop.getRemoteServiceChannelCallbacks();
- if (callbacks.containsKey(address)) {
- Log.w(TAG, "SDP request already in progress for " + address);
- return false;
- }
- // Protect from malicious clients - only allow 32 bonding requests per minute.
- if (callbacks.size() > MAX_OUTSTANDING_ASYNC) {
- Log.w(TAG, "Too many outstanding SDP requests, dropping request for " + address);
- return false;
- }
- callbacks.put(address, callback);
-
- if (!getRemoteServiceChannelNative(address, (short)uuid16)) {
- callbacks.remove(address);
- return false;
- }
- return true;
- }
- private native boolean getRemoteServiceChannelNative(String address, short uuid16);
-
- public synchronized boolean setPin(String address, byte[] pin) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (pin == null || pin.length <= 0 || pin.length > 16 ||
- !BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- address = address.toUpperCase();
- Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
- if (data == null) {
- Log.w(TAG, "setPin(" + address + ") called but no native data available, " +
- "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
- " or by bluez.\n");
- return false;
- }
- // bluez API wants pin as a string
- String pinString;
- try {
- pinString = new String(pin, "UTF8");
- } catch (UnsupportedEncodingException uee) {
- Log.e(TAG, "UTF8 not supported?!?");
- return false;
- }
- return setPinNative(address, pinString, data.intValue());
- }
- private native boolean setPinNative(String address, String pin, int nativeData);
-
- public synchronized boolean cancelPin(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- address = address.toUpperCase();
- Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
- if (data == null) {
- Log.w(TAG, "cancelPin(" + address + ") called but no native data available, " +
- "ignoring. Maybe the PasskeyAgent Request was already cancelled by the remote " +
- "or by bluez.\n");
- return false;
- }
- return cancelPinNative(address, data.intValue());
- }
- private native boolean cancelPinNative(String address, int natveiData);
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
- ContentResolver resolver = context.getContentResolver();
- // Query the airplane mode from Settings.System just to make sure that
- // some random app is not sending this intent and disabling bluetooth
- boolean enabled = !isAirplaneModeOn();
- // If bluetooth is currently expected to be on, then enable or disable bluetooth
- if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
- if (enabled) {
- enable(null, false);
- } else {
- disable(false);
- }
- }
- }
- }
- };
-
- private void registerForAirplaneMode() {
- String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
- Settings.System.AIRPLANE_MODE_RADIOS);
- mIsAirplaneSensitive = airplaneModeRadios == null
- ? true : airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
- if (mIsAirplaneSensitive) {
- mIntentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- mContext.registerReceiver(mReceiver, mIntentFilter);
- }
- }
-
- /* Returns true if airplane mode is currently on */
- private final boolean isAirplaneModeOn() {
- return Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.AIRPLANE_MODE_ON, 0) == 1;
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mIsEnabled) {
- pw.println("\nBluetooth ENABLED: " + getAddress() + " (" + getName() + ")");
- pw.println("\nisDiscovering() = " + isDiscovering());
-
- BluetoothHeadset headset = new BluetoothHeadset(mContext, null);
-
- String[] addresses = listRemoteDevices();
-
- pw.println("\n--Known devices--");
- for (String address : addresses) {
- pw.printf("%s %10s (%d) %s\n", address,
- toBondStateString(mBondState.getBondState(address)),
- mBondState.getAttempt(address),
- getRemoteName(address));
- }
-
- addresses = listAclConnections();
- pw.println("\n--ACL connected devices--");
- for (String address : addresses) {
- pw.println(address);
- }
-
- // Rather not do this from here, but no-where else and I need this
- // dump
- pw.println("\n--Headset Service--");
- switch (headset.getState()) {
- case BluetoothHeadset.STATE_DISCONNECTED:
- pw.println("getState() = STATE_DISCONNECTED");
- break;
- case BluetoothHeadset.STATE_CONNECTING:
- pw.println("getState() = STATE_CONNECTING");
- break;
- case BluetoothHeadset.STATE_CONNECTED:
- pw.println("getState() = STATE_CONNECTED");
- break;
- case BluetoothHeadset.STATE_ERROR:
- pw.println("getState() = STATE_ERROR");
- break;
- }
- pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress());
- headset.close();
-
- } else {
- pw.println("\nBluetooth DISABLED");
- }
- pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive);
- }
-
- /* package */ static int bluezStringToScanMode(String mode) {
- if (mode == null) {
- return BluetoothError.ERROR;
- }
- mode = mode.toLowerCase();
- if (mode.equals("off")) {
- return BluetoothDevice.SCAN_MODE_NONE;
- } else if (mode.equals("connectable")) {
- return BluetoothDevice.SCAN_MODE_CONNECTABLE;
- } else if (mode.equals("discoverable")) {
- return BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
- } else {
- return BluetoothError.ERROR;
- }
- }
-
- /* package */ static String scanModeToBluezString(int mode) {
- switch (mode) {
- case BluetoothDevice.SCAN_MODE_NONE:
- return "off";
- case BluetoothDevice.SCAN_MODE_CONNECTABLE:
- return "connectable";
- case BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
- return "discoverable";
- }
- return null;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
deleted file mode 100644
index 8b09583..0000000
--- a/core/java/android/server/BluetoothEventLoop.java
+++ /dev/null
@@ -1,373 +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 android.server;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothError;
-import android.bluetooth.BluetoothIntent;
-import android.bluetooth.IBluetoothDeviceCallback;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.HashMap;
-
-/**
- * TODO: Move this to
- * java/services/com/android/server/BluetoothEventLoop.java
- * and make the contructor package private again.
- *
- * @hide
- */
-class BluetoothEventLoop {
- private static final String TAG = "BluetoothEventLoop";
- private static final boolean DBG = false;
-
- private int mNativeData;
- private Thread mThread;
- private boolean mInterrupted;
- private HashMap<String, Integer> mPasskeyAgentRequestData;
- private HashMap<String, IBluetoothDeviceCallback> mGetRemoteServiceChannelCallbacks;
- private BluetoothDeviceService mBluetoothService;
- private Context mContext;
-
- private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
-
- // The time (in millisecs) to delay the pairing attempt after the first
- // auto pairing attempt fails. We use an exponential delay with
- // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and
- // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value.
- private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000;
- private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000;
-
- private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
- private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
- String address = (String)msg.obj;
- if (address != null) {
- mBluetoothService.createBond(address);
- return;
- }
- break;
- }
- }
- };
-
- static { classInitNative(); }
- private static native void classInitNative();
-
- /* pacakge */ BluetoothEventLoop(Context context, BluetoothDeviceService bluetoothService) {
- mBluetoothService = bluetoothService;
- mContext = context;
- mPasskeyAgentRequestData = new HashMap();
- mGetRemoteServiceChannelCallbacks = new HashMap();
- initializeNativeDataNative();
- }
- private native void initializeNativeDataNative();
-
- protected void finalize() throws Throwable {
- try {
- cleanupNativeDataNative();
- } finally {
- super.finalize();
- }
- }
- private native void cleanupNativeDataNative();
-
- /* pacakge */ HashMap<String, IBluetoothDeviceCallback> getRemoteServiceChannelCallbacks() {
- return mGetRemoteServiceChannelCallbacks;
- }
-
- /* pacakge */ HashMap<String, Integer> getPasskeyAgentRequestData() {
- return mPasskeyAgentRequestData;
- }
-
- private synchronized boolean waitForAndDispatchEvent(int timeout_ms) {
- return waitForAndDispatchEventNative(timeout_ms);
- }
- private native boolean waitForAndDispatchEventNative(int timeout_ms);
-
- /* package */ synchronized void start() {
-
- if (mThread != null) {
- // Already running.
- return;
- }
- mThread = new Thread("Bluetooth Event Loop") {
- @Override
- public void run() {
- try {
- if (setUpEventLoopNative()) {
- while (!mInterrupted) {
- waitForAndDispatchEvent(0);
- sleep(500);
- }
- tearDownEventLoopNative();
- }
- } catch (InterruptedException e) { }
- if (DBG) log("Event Loop thread finished");
- }
- };
- if (DBG) log("Starting Event Loop thread");
- mInterrupted = false;
- mThread.start();
- }
- private native boolean setUpEventLoopNative();
- private native void tearDownEventLoopNative();
-
- public synchronized void stop() {
- if (mThread != null) {
- mInterrupted = true;
- try {
- mThread.join();
- mThread = null;
- } catch (InterruptedException e) {
- Log.i(TAG, "Interrupted waiting for Event Loop thread to join");
- }
- }
- }
-
- public synchronized boolean isEventLoopRunning() {
- return mThread != null;
- }
-
- /*package*/ void onModeChanged(String bluezMode) {
- int mode = BluetoothDeviceService.bluezStringToScanMode(bluezMode);
- if (mode >= 0) {
- Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.SCAN_MODE, mode);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- }
-
- private void onDiscoveryStarted() {
- mBluetoothService.setIsDiscovering(true);
- Intent intent = new Intent(BluetoothIntent.DISCOVERY_STARTED_ACTION);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onDiscoveryCompleted() {
- mBluetoothService.setIsDiscovering(false);
- Intent intent = new Intent(BluetoothIntent.DISCOVERY_COMPLETED_ACTION);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
- private void onRemoteDeviceFound(String address, int deviceClass, short rssi) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.CLASS, deviceClass);
- intent.putExtra(BluetoothIntent.RSSI, rssi);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteDeviceDisappeared(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISAPPEARED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteClassUpdated(String address, int deviceClass) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_CLASS_UPDATED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.CLASS, deviceClass);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteDeviceConnected(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteDeviceDisconnectRequested(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISCONNECT_REQUESTED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteDeviceDisconnected(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISCONNECTED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteNameUpdated(String address, String name) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_UPDATED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.NAME, name);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteNameFailed(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_FAILED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteNameChanged(String address, String name) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_UPDATED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.NAME, name);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
- private void onCreateBondingResult(String address, int result) {
- address = address.toUpperCase();
- if (result == BluetoothError.SUCCESS) {
- mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED);
- if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
- mBluetoothService.getBondState().clearPinAttempts(address);
- }
- } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED &&
- mBluetoothService.getBondState().getAttempt(address) == 1) {
- mBluetoothService.getBondState().addAutoPairingFailure(address);
- pairingAttempt(address, result);
- } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN &&
- mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
- pairingAttempt(address, result);
- } else {
- mBluetoothService.getBondState().setBondState(address,
- BluetoothDevice.BOND_NOT_BONDED, result);
- if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
- mBluetoothService.getBondState().clearPinAttempts(address);
- }
- }
- }
-
- private void pairingAttempt(String address, int result) {
- // This happens when our initial guess of "0000" as the pass key
- // fails. Try to create the bond again and display the pin dialog
- // to the user. Use back-off while posting the delayed
- // message. The initial value is
- // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is
- // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is
- // reached, display an error to the user.
- int attempt = mBluetoothService.getBondState().getAttempt(address);
- if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY >
- MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) {
- mBluetoothService.getBondState().clearPinAttempts(address);
- mBluetoothService.getBondState().setBondState(address,
- BluetoothDevice.BOND_NOT_BONDED, result);
- return;
- }
-
- Message message = mHandler.obtainMessage(EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
- message.obj = address;
- boolean postResult = mHandler.sendMessageDelayed(message,
- attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
- if (!postResult) {
- mBluetoothService.getBondState().clearPinAttempts(address);
- mBluetoothService.getBondState().setBondState(address,
- BluetoothDevice.BOND_NOT_BONDED, result);
- return;
- }
- mBluetoothService.getBondState().attempt(address);
- }
-
- private void onBondingCreated(String address) {
- mBluetoothService.getBondState().setBondState(address.toUpperCase(),
- BluetoothDevice.BOND_BONDED);
- }
-
- private void onBondingRemoved(String address) {
- mBluetoothService.getBondState().setBondState(address.toUpperCase(),
- BluetoothDevice.BOND_NOT_BONDED, BluetoothDevice.UNBOND_REASON_REMOVED);
- }
-
- private void onNameChanged(String name) {
- Intent intent = new Intent(BluetoothIntent.NAME_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.NAME, name);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
- private void onPasskeyAgentRequest(String address, int nativeData) {
- address = address.toUpperCase();
- mPasskeyAgentRequestData.put(address, new Integer(nativeData));
-
- if (mBluetoothService.getBondState().getBondState(address) ==
- BluetoothDevice.BOND_BONDING) {
- // we initiated the bonding
- int btClass = mBluetoothService.getRemoteClass(address);
-
- // try 0000 once if the device looks dumb
- switch (BluetoothClass.Device.getDevice(btClass)) {
- case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
- case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
- case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
- case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
- case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
- if (!mBluetoothService.getBondState().hasAutoPairingFailed(address) &&
- !mBluetoothService.getBondState().isAutoPairingBlacklisted(address)) {
- mBluetoothService.getBondState().attempt(address);
- mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000"));
- return;
- }
- }
- }
- Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
- }
-
- private void onPasskeyAgentCancel(String address) {
- address = address.toUpperCase();
- mPasskeyAgentRequestData.remove(address);
- Intent intent = new Intent(BluetoothIntent.PAIRING_CANCEL_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
- mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NOT_BONDED,
- BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
- }
-
- private boolean onAuthAgentAuthorize(String address, String service, String uuid) {
- boolean authorized = false;
- if (service.endsWith("service_audio")) {
- BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
- authorized = a2dp.getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF;
- if (authorized) {
- Log.i(TAG, "Allowing incoming A2DP connection from " + address);
- } else {
- Log.i(TAG, "Rejecting incoming A2DP connection from " + address);
- }
- } else {
- Log.i(TAG, "Rejecting incoming " + service + " connection from " + address);
- }
- return authorized;
- }
-
- private void onAuthAgentCancel(String address, String service, String uuid) {
- // We immediately response to DBUS Authorize() so this should not
- // usually happen
- log("onAuthAgentCancel(" + address + ", " + service + ", " + uuid + ")");
- }
-
- private void onGetRemoteServiceChannelResult(String address, int channel) {
- IBluetoothDeviceCallback callback = mGetRemoteServiceChannelCallbacks.get(address);
- if (callback != null) {
- mGetRemoteServiceChannelCallbacks.remove(address);
- try {
- callback.onGetRemoteServiceChannelResult(address, channel);
- } catch (RemoteException e) {}
- }
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/server/data/BuildData.java b/core/java/android/server/data/BuildData.java
deleted file mode 100644
index 53ffa3f..0000000
--- a/core/java/android/server/data/BuildData.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.server.data;
-
-import android.os.Build;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import static com.android.internal.util.Objects.nonNull;
-
-/**
- * Build data transfer object. Keep in sync. with the server side version.
- */
-public class BuildData {
-
- /** The version of the data returned by write() and understood by the constructor. */
- private static final int VERSION = 0;
-
- private final String fingerprint;
- private final String incrementalVersion;
- private final long time; // in *seconds* since the epoch (not msec!)
-
- public BuildData() {
- this.fingerprint = "android:" + Build.FINGERPRINT;
- this.incrementalVersion = Build.VERSION.INCREMENTAL;
- this.time = Build.TIME / 1000; // msec -> sec
- }
-
- public BuildData(String fingerprint, String incrementalVersion, long time) {
- this.fingerprint = nonNull(fingerprint);
- this.incrementalVersion = incrementalVersion;
- this.time = time;
- }
-
- /*package*/ BuildData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != VERSION) {
- throw new IOException("Expected " + VERSION + ". Got: " + dataVersion);
- }
-
- this.fingerprint = in.readUTF();
- this.incrementalVersion = Long.toString(in.readLong());
- this.time = in.readLong();
- }
-
- /*package*/ void write(DataOutput out) throws IOException {
- out.writeInt(VERSION);
- out.writeUTF(fingerprint);
-
- // TODO: change the format/version to expect a string for this field.
- // Version 0, still used by the server side, expects a long.
- long changelist;
- try {
- changelist = Long.parseLong(incrementalVersion);
- } catch (NumberFormatException ex) {
- changelist = -1;
- }
- out.writeLong(changelist);
- out.writeLong(time);
- }
-
- public String getFingerprint() {
- return fingerprint;
- }
-
- public String getIncrementalVersion() {
- return incrementalVersion;
- }
-
- public long getTime() {
- return time;
- }
-}
diff --git a/core/java/android/server/data/CrashData.java b/core/java/android/server/data/CrashData.java
deleted file mode 100644
index d652bb3..0000000
--- a/core/java/android/server/data/CrashData.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import static com.android.internal.util.Objects.nonNull;
-
-/**
- * Crash data transfer object. Keep in sync. with the server side version.
- */
-public class CrashData {
-
- final String id;
- final String activity;
- final long time;
- final BuildData buildData;
- final ThrowableData throwableData;
- final byte[] state;
-
- public CrashData(String id, String activity, BuildData buildData,
- ThrowableData throwableData) {
- this.id = nonNull(id);
- this.activity = nonNull(activity);
- this.buildData = nonNull(buildData);
- this.throwableData = nonNull(throwableData);
- this.time = System.currentTimeMillis();
- this.state = null;
- }
-
- public CrashData(String id, String activity, BuildData buildData,
- ThrowableData throwableData, byte[] state) {
- this.id = nonNull(id);
- this.activity = nonNull(activity);
- this.buildData = nonNull(buildData);
- this.throwableData = nonNull(throwableData);
- this.time = System.currentTimeMillis();
- this.state = state;
- }
-
- public CrashData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0 && dataVersion != 1) {
- throw new IOException("Expected 0 or 1. Got: " + dataVersion);
- }
-
- this.id = in.readUTF();
- this.activity = in.readUTF();
- this.time = in.readLong();
- this.buildData = new BuildData(in);
- this.throwableData = new ThrowableData(in);
- if (dataVersion == 1) {
- int len = in.readInt();
- if (len == 0) {
- this.state = null;
- } else {
- this.state = new byte[len];
- in.readFully(this.state, 0, len);
- }
- } else {
- this.state = null;
- }
- }
-
- public CrashData(String tag, Throwable throwable) {
- id = "";
- activity = tag;
- buildData = new BuildData();
- throwableData = new ThrowableData(throwable);
- time = System.currentTimeMillis();
- state = null;
- }
-
- public void write(DataOutput out) throws IOException {
- // version
- if (this.state == null) {
- out.writeInt(0);
- } else {
- out.writeInt(1);
- }
-
- out.writeUTF(this.id);
- out.writeUTF(this.activity);
- out.writeLong(this.time);
- buildData.write(out);
- throwableData.write(out);
- if (this.state != null) {
- out.writeInt(this.state.length);
- out.write(this.state, 0, this.state.length);
- }
- }
-
- public BuildData getBuildData() {
- return buildData;
- }
-
- public ThrowableData getThrowableData() {
- return throwableData;
- }
-
- public String getId() {
- return id;
- }
-
- public String getActivity() {
- return activity;
- }
-
- public long getTime() {
- return time;
- }
-
- public byte[] getState() {
- return state;
- }
-
- /**
- * Return a brief description of this CrashData record. The details of the
- * representation are subject to change.
- *
- * @return Returns a String representing the contents of the object.
- */
- @Override
- public String toString() {
- return "[CrashData: id=" + id + " activity=" + activity + " time=" + time +
- " buildData=" + buildData.toString() +
- " throwableData=" + throwableData.toString() + "]";
- }
-}
diff --git a/core/java/android/server/data/StackTraceElementData.java b/core/java/android/server/data/StackTraceElementData.java
deleted file mode 100644
index 07185a0..0000000
--- a/core/java/android/server/data/StackTraceElementData.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-/**
- * Stack trace element data transfer object. Keep in sync. with the server side
- * version.
- */
-public class StackTraceElementData {
-
- final String className;
- final String fileName;
- final String methodName;
- final int lineNumber;
-
- public StackTraceElementData(StackTraceElement element) {
- this.className = element.getClassName();
-
- String fileName = element.getFileName();
- this.fileName = fileName == null ? "[unknown source]" : fileName;
-
- this.methodName = element.getMethodName();
- this.lineNumber = element.getLineNumber();
- }
-
- public StackTraceElementData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0) {
- throw new IOException("Expected 0. Got: " + dataVersion);
- }
-
- this.className = in.readUTF();
- this.fileName = in.readUTF();
- this.methodName = in.readUTF();
- this.lineNumber = in.readInt();
- }
-
- void write(DataOutput out) throws IOException {
- out.writeInt(0); // version
-
- out.writeUTF(className);
- out.writeUTF(fileName);
- out.writeUTF(methodName);
- out.writeInt(lineNumber);
- }
-
- public String getClassName() {
- return className;
- }
-
- public String getFileName() {
- return fileName;
- }
-
- public String getMethodName() {
- return methodName;
- }
-
- public int getLineNumber() {
- return lineNumber;
- }
-}
diff --git a/core/java/android/server/data/ThrowableData.java b/core/java/android/server/data/ThrowableData.java
deleted file mode 100644
index e500aca..0000000
--- a/core/java/android/server/data/ThrowableData.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-/**
- * Throwable data transfer object. Keep in sync. with the server side version.
- */
-public class ThrowableData {
-
- final String message;
- final String type;
- final StackTraceElementData[] stackTrace;
- final ThrowableData cause;
-
- public ThrowableData(Throwable throwable) {
- this.type = throwable.getClass().getName();
- String message = throwable.getMessage();
- this.message = message == null ? "" : message;
-
- StackTraceElement[] elements = throwable.getStackTrace();
- this.stackTrace = new StackTraceElementData[elements.length];
- for (int i = 0; i < elements.length; i++) {
- this.stackTrace[i] = new StackTraceElementData(elements[i]);
- }
-
- Throwable cause = throwable.getCause();
- this.cause = cause == null ? null : new ThrowableData(cause);
- }
-
- public ThrowableData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0) {
- throw new IOException("Expected 0. Got: " + dataVersion);
- }
-
- this.message = in.readUTF();
- this.type = in.readUTF();
-
- int count = in.readInt();
- this.stackTrace = new StackTraceElementData[count];
- for (int i = 0; i < count; i++) {
- this.stackTrace[i] = new StackTraceElementData(in);
- }
-
- this.cause = in.readBoolean() ? new ThrowableData(in) : null;
- }
-
- public void write(DataOutput out) throws IOException {
- out.writeInt(0); // version
-
- out.writeUTF(message);
- out.writeUTF(type);
-
- out.writeInt(stackTrace.length);
- for (StackTraceElementData elementData : stackTrace) {
- elementData.write(out);
- }
-
- out.writeBoolean(cause != null);
- if (cause != null) {
- cause.write(out);
- }
- }
-
- public String getMessage() {
- return message;
- }
-
- public String getType() {
- return type;
- }
-
- public StackTraceElementData[] getStackTrace() {
- return stackTrace;
- }
-
- public ThrowableData getCause() {
- return cause;
- }
-
-
- public String toString() {
- return toString(null);
- }
-
- public String toString(String prefix) {
- StringBuilder builder = new StringBuilder();
- append(prefix, builder, this);
- return builder.toString();
- }
-
- private static void append(String prefix, StringBuilder builder,
- ThrowableData throwableData) {
- if (prefix != null) builder.append(prefix);
- builder.append(throwableData.getType())
- .append(": ")
- .append(throwableData.getMessage())
- .append('\n');
- for (StackTraceElementData element : throwableData.getStackTrace()) {
- if (prefix != null ) builder.append(prefix);
- builder.append(" at ")
- .append(element.getClassName())
- .append('.')
- .append(element.getMethodName())
- .append("(")
- .append(element.getFileName())
- .append(':')
- .append(element.getLineNumber())
- .append(")\n");
-
- }
-
- ThrowableData cause = throwableData.getCause();
- if (cause != null) {
- if (prefix != null ) builder.append(prefix);
- builder.append("Caused by: ");
- append(prefix, builder, cause);
- }
- }
-}
diff --git a/core/java/android/server/data/package.html b/core/java/android/server/data/package.html
deleted file mode 100755
index 1c9bf9d..0000000
--- a/core/java/android/server/data/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body>
- {@hide}
-</body>
-</html>
diff --git a/core/java/android/server/package.html b/core/java/android/server/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/android/server/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
deleted file mode 100644
index fe15553..0000000
--- a/core/java/android/server/search/SearchManagerService.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.server.search;
-
-import android.app.ISearchManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.util.Config;
-
-/**
- * This is a simplified version of the Search Manager service. It no longer handles
- * presentation (UI). Its function is to maintain the map & list of "searchable"
- * items, which provides a mapping from individual activities (where a user might have
- * invoked search) to specific searchable activities (where the search will be dispatched).
- */
-public class SearchManagerService extends ISearchManager.Stub
-{
- // general debugging support
- private static final String TAG = "SearchManagerService";
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- // configuration choices
- private static final boolean IMMEDIATE_SEARCHABLES_UPDATE = true;
-
- // class maintenance and general shared data
- private final Context mContext;
- private final Handler mHandler;
- private boolean mSearchablesDirty;
-
- /**
- * Initialize the Search Manager service in the provided system context.
- * Only one instance of this object should be created!
- *
- * @param context to use for accessing DB, window manager, etc.
- */
- public SearchManagerService(Context context) {
- mContext = context;
- mHandler = new Handler();
-
- // Setup the infrastructure for updating and maintaining the list
- // of searchable activities.
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addDataScheme("package");
- mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
- mSearchablesDirty = true;
-
- // After startup settles down, preload the searchables list,
- // which will reduce the delay when the search UI is invoked.
- if (IMMEDIATE_SEARCHABLES_UPDATE) {
- mHandler.post(mRunUpdateSearchable);
- }
- }
-
- /**
- * Listens for intent broadcasts.
- *
- * The primary purpose here is to refresh the "searchables" list
- * if packages are added/removed.
- */
- private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- // First, test for intents that matter at any time
- if (action.equals(Intent.ACTION_PACKAGE_ADDED) ||
- action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
- action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
- mSearchablesDirty = true;
- if (IMMEDIATE_SEARCHABLES_UPDATE) {
- mHandler.post(mRunUpdateSearchable);
- }
- return;
- }
- }
- };
-
- /**
- * This runnable (for the main handler / UI thread) will update the searchables list.
- */
- private Runnable mRunUpdateSearchable = new Runnable() {
- public void run() {
- if (mSearchablesDirty) {
- updateSearchables();
- }
- }
- };
-
- /**
- * Update the list of searchables, either at startup or in response to
- * a package add/remove broadcast message.
- */
- private void updateSearchables() {
- SearchableInfo.buildSearchableList(mContext);
- mSearchablesDirty = false;
-
- // TODO This is a hack. This shouldn't be hardcoded here, it's probably
- // a policy.
-// ComponentName defaultSearch = new ComponentName(
-// "com.android.contacts",
-// "com.android.contacts.ContactsListActivity" );
- ComponentName defaultSearch = new ComponentName(
- "com.android.googlesearch",
- "com.android.googlesearch.GoogleSearch" );
- SearchableInfo.setDefaultSearchable(mContext, defaultSearch);
- }
-
- /**
- * Return the searchableinfo for a given activity
- *
- * @param launchActivity The activity from which we're launching this search.
- * @return Returns a SearchableInfo record describing the parameters of the search,
- * or null if no searchable metadata was available.
- * @param globalSearch If false, this will only launch the search that has been specifically
- * defined by the application (which is usually defined as a local search). If no default
- * search is defined in the current application or activity, no search will be launched.
- * If true, this will always launch a platform-global (e.g. web-based) search instead.
- */
- public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) {
- // final check. however we should try to avoid this, because
- // it slows down the entry into the UI.
- if (mSearchablesDirty) {
- updateSearchables();
- }
- SearchableInfo si = null;
- if (globalSearch) {
- si = SearchableInfo.getDefaultSearchable();
- } else {
- si = SearchableInfo.getSearchableInfo(mContext, launchActivity);
- }
-
- return si;
- }
-}
diff --git a/core/java/android/server/search/SearchableInfo.aidl b/core/java/android/server/search/SearchableInfo.aidl
deleted file mode 100644
index 9576c2b..0000000
--- a/core/java/android/server/search/SearchableInfo.aidl
+++ /dev/null
@@ -1,19 +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 android.server.search;
-
-parcelable SearchableInfo;
diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java
deleted file mode 100644
index c18675e..0000000
--- a/core/java/android/server/search/SearchableInfo.java
+++ /dev/null
@@ -1,850 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.server.search;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.InputType;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Xml;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-public final class SearchableInfo implements Parcelable {
-
- // general debugging support
- final static String LOG_TAG = "SearchableInfo";
-
- // set this flag to 1 to prevent any apps from providing suggestions
- final static int DBG_INHIBIT_SUGGESTIONS = 0;
-
- // static strings used for XML lookups, etc.
- // TODO how should these be documented for the developer, in a more structured way than
- // the current long wordy javadoc in SearchManager.java ?
- private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable";
- private static final String MD_LABEL_SEARCHABLE = "android.app.searchable";
- private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*";
- private static final String MD_XML_ELEMENT_SEARCHABLE = "searchable";
- private static final String MD_XML_ELEMENT_SEARCHABLE_ACTION_KEY = "actionkey";
-
- // class maintenance and general shared data
- private static HashMap<ComponentName, SearchableInfo> sSearchablesMap = null;
- private static ArrayList<SearchableInfo> sSearchablesList = null;
- private static SearchableInfo sDefaultSearchable = null;
-
- // true member variables - what we know about the searchability
- // TO-DO replace public with getters
- public boolean mSearchable = false;
- private int mLabelId = 0;
- public ComponentName mSearchActivity = null;
- private int mHintId = 0;
- private int mSearchMode = 0;
- public boolean mBadgeLabel = false;
- public boolean mBadgeIcon = false;
- public boolean mQueryRewriteFromData = false;
- public boolean mQueryRewriteFromText = false;
- private int mIconId = 0;
- private int mSearchButtonText = 0;
- private int mSearchInputType = 0;
- private String mSuggestAuthority = null;
- private String mSuggestPath = null;
- private String mSuggestSelection = null;
- private String mSuggestIntentAction = null;
- private String mSuggestIntentData = null;
- private ActionKeyInfo mActionKeyList = null;
- private String mSuggestProviderPackage = null;
- private Context mCacheActivityContext = null; // use during setup only - don't hold memory!
-
- // Flag values for Searchable_voiceSearchMode
- private static int VOICE_SEARCH_SHOW_BUTTON = 1;
- private static int VOICE_SEARCH_LAUNCH_WEB_SEARCH = 2;
- private static int VOICE_SEARCH_LAUNCH_RECOGNIZER = 4;
- private int mVoiceSearchMode = 0;
- private int mVoiceLanguageModeId; // voiceLanguageModel
- private int mVoicePromptTextId; // voicePromptText
- private int mVoiceLanguageId; // voiceLanguage
- private int mVoiceMaxResults; // voiceMaxResults
-
- /**
- * Set the default searchable activity (when none is specified).
- */
- public static void setDefaultSearchable(Context context,
- ComponentName activity) {
- synchronized (SearchableInfo.class) {
- SearchableInfo si = null;
- if (activity != null) {
- si = getSearchableInfo(context, activity);
- if (si != null) {
- // move to front of list
- sSearchablesList.remove(si);
- sSearchablesList.add(0, si);
- }
- }
- sDefaultSearchable = si;
- }
- }
-
- /**
- * Provides the system-default search activity, which you can use
- * whenever getSearchableInfo() returns null;
- *
- * @return Returns the system-default search activity, null if never defined
- */
- public static SearchableInfo getDefaultSearchable() {
- synchronized (SearchableInfo.class) {
- return sDefaultSearchable;
- }
- }
-
- /**
- * Retrieve the authority for obtaining search suggestions.
- *
- * @return Returns a string containing the suggestions authority.
- */
- public String getSuggestAuthority() {
- return mSuggestAuthority;
- }
-
- /**
- * Retrieve the path for obtaining search suggestions.
- *
- * @return Returns a string containing the suggestions path, or null if not provided.
- */
- public String getSuggestPath() {
- return mSuggestPath;
- }
-
- /**
- * Retrieve the selection pattern for obtaining search suggestions. This must
- * include a single ? which will be used for the user-typed characters.
- *
- * @return Returns a string containing the suggestions authority.
- */
- public String getSuggestSelection() {
- return mSuggestSelection;
- }
-
- /**
- * Retrieve the (optional) intent action for use with these suggestions. This is
- * useful if all intents will have the same action (e.g. "android.intent.action.VIEW").
- *
- * Can be overriden in any given suggestion via the AUTOSUGGEST_COLUMN_INTENT_ACTION column.
- *
- * @return Returns a string containing the default intent action.
- */
- public String getSuggestIntentAction() {
- return mSuggestIntentAction;
- }
-
- /**
- * Retrieve the (optional) intent data for use with these suggestions. This is
- * useful if all intents will have similar data URIs (e.g. "android.intent.action.VIEW"),
- * but you'll likely need to provide a specific ID as well via the column
- * AUTOSUGGEST_COLUMN_INTENT_DATA_ID, which will be appended to the intent data URI.
- *
- * Can be overriden in any given suggestion via the AUTOSUGGEST_COLUMN_INTENT_DATA column.
- *
- * @return Returns a string containing the default intent data.
- */
- public String getSuggestIntentData() {
- return mSuggestIntentData;
- }
-
- /**
- * Get the context for the searchable activity.
- *
- * This is fairly expensive so do it on the original scan, or when an app is
- * selected, but don't hang on to the result forever.
- *
- * @param context You need to supply a context to start with
- * @return Returns a context related to the searchable activity
- */
- public Context getActivityContext(Context context) {
- Context theirContext = null;
- try {
- theirContext = context.createPackageContext(mSearchActivity.getPackageName(), 0);
- } catch (PackageManager.NameNotFoundException e) {
- // unexpected, but we deal with this by null-checking theirContext
- } catch (java.lang.SecurityException e) {
- // unexpected, but we deal with this by null-checking theirContext
- }
-
- return theirContext;
- }
-
- /**
- * Get the context for the suggestions provider.
- *
- * This is fairly expensive so do it on the original scan, or when an app is
- * selected, but don't hang on to the result forever.
- *
- * @param context You need to supply a context to start with
- * @param activityContext If we can determine that the provider and the activity are the
- * same, we'll just return this one.
- * @return Returns a context related to the context provider
- */
- public Context getProviderContext(Context context, Context activityContext) {
- Context theirContext = null;
- if (mSearchActivity.getPackageName().equals(mSuggestProviderPackage)) {
- return activityContext;
- }
- if (mSuggestProviderPackage != null)
- try {
- theirContext = context.createPackageContext(mSuggestProviderPackage, 0);
- } catch (PackageManager.NameNotFoundException e) {
- // unexpected, but we deal with this by null-checking theirContext
- } catch (java.lang.SecurityException e) {
- // unexpected, but we deal with this by null-checking theirContext
- }
-
- return theirContext;
- }
-
- /**
- * Factory. Look up, or construct, based on the activity.
- *
- * The activities fall into three cases, based on meta-data found in
- * the manifest entry:
- * <ol>
- * <li>The activity itself implements search. This is indicated by the
- * presence of a "android.app.searchable" meta-data attribute.
- * The value is a reference to an XML file containing search information.</li>
- * <li>A related activity implements search. This is indicated by the
- * presence of a "android.app.default_searchable" meta-data attribute.
- * The value is a string naming the activity implementing search. In this
- * case the factory will "redirect" and return the searchable data.</li>
- * <li>No searchability data is provided. We return null here and other
- * code will insert the "default" (e.g. contacts) search.
- *
- * TODO: cache the result in the map, and check the map first.
- * TODO: it might make sense to implement the searchable reference as
- * an application meta-data entry. This way we don't have to pepper each
- * and every activity.
- * TODO: can we skip the constructor step if it's a non-searchable?
- * TODO: does it make sense to plug the default into a slot here for
- * automatic return? Probably not, but it's one way to do it.
- *
- * @param activity The name of the current activity, or null if the
- * activity does not define any explicit searchable metadata.
- */
- public static SearchableInfo getSearchableInfo(Context context,
- ComponentName activity) {
- // Step 1. Is the result already hashed? (case 1)
- SearchableInfo result;
- synchronized (SearchableInfo.class) {
- result = sSearchablesMap.get(activity);
- if (result != null) return result;
- }
-
- // Step 2. See if the current activity references a searchable.
- // Note: Conceptually, this could be a while(true) loop, but there's
- // no point in implementing reference chaining here and risking a loop.
- // References must point directly to searchable activities.
-
- ActivityInfo ai = null;
- XmlPullParser xml = null;
- try {
- ai = context.getPackageManager().
- getActivityInfo(activity, PackageManager.GET_META_DATA );
- String refActivityName = null;
-
- // First look for activity-specific reference
- Bundle md = ai.metaData;
- if (md != null) {
- refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
- }
- // If not found, try for app-wide reference
- if (refActivityName == null) {
- md = ai.applicationInfo.metaData;
- if (md != null) {
- refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
- }
- }
-
- // Irrespective of source, if a reference was found, follow it.
- if (refActivityName != null)
- {
- // An app or activity can declare that we should simply launch
- // "system default search" if search is invoked.
- if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
- return getDefaultSearchable();
- }
- String pkg = activity.getPackageName();
- ComponentName referredActivity;
- if (refActivityName.charAt(0) == '.') {
- referredActivity = new ComponentName(pkg, pkg + refActivityName);
- } else {
- referredActivity = new ComponentName(pkg, refActivityName);
- }
-
- // Now try the referred activity, and if found, cache
- // it against the original name so we can skip the check
- synchronized (SearchableInfo.class) {
- result = sSearchablesMap.get(referredActivity);
- if (result != null) {
- sSearchablesMap.put(activity, result);
- return result;
- }
- }
- }
- } catch (PackageManager.NameNotFoundException e) {
- // case 3: no metadata
- }
-
- // Step 3. None found. Return null.
- return null;
-
- }
-
- /**
- * Super-factory. Builds an entire list (suitable for display) of
- * activities that are searchable, by iterating the entire set of
- * ACTION_SEARCH intents.
- *
- * Also clears the hash of all activities -> searches which will
- * refill as the user clicks "search".
- *
- * This should only be done at startup and again if we know that the
- * list has changed.
- *
- * TODO: every activity that provides a ACTION_SEARCH intent should
- * also provide searchability meta-data. There are a bunch of checks here
- * that, if data is not found, silently skip to the next activity. This
- * won't help a developer trying to figure out why their activity isn't
- * showing up in the list, but an exception here is too rough. I would
- * like to find a better notification mechanism.
- *
- * TODO: sort the list somehow? UI choice.
- *
- * @param context a context we can use during this work
- */
- public static void buildSearchableList(Context context) {
-
- // create empty hash & list
- HashMap<ComponentName, SearchableInfo> newSearchablesMap
- = new HashMap<ComponentName, SearchableInfo>();
- ArrayList<SearchableInfo> newSearchablesList
- = new ArrayList<SearchableInfo>();
-
- // use intent resolver to generate list of ACTION_SEARCH receivers
- final PackageManager pm = context.getPackageManager();
- List<ResolveInfo> infoList;
- final Intent intent = new Intent(Intent.ACTION_SEARCH);
- infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
-
- // analyze each one, generate a Searchables record, and record
- if (infoList != null) {
- int count = infoList.size();
- for (int ii = 0; ii < count; ii++) {
- // for each component, try to find metadata
- ResolveInfo info = infoList.get(ii);
- ActivityInfo ai = info.activityInfo;
- XmlResourceParser xml = ai.loadXmlMetaData(context.getPackageManager(),
- MD_LABEL_SEARCHABLE);
- if (xml == null) {
- continue;
- }
- ComponentName cName = new ComponentName(
- info.activityInfo.packageName,
- info.activityInfo.name);
-
- SearchableInfo searchable = getActivityMetaData(context, xml, cName);
- xml.close();
-
- if (searchable != null) {
- // no need to keep the context any longer. setup time is over.
- searchable.mCacheActivityContext = null;
-
- newSearchablesList.add(searchable);
- newSearchablesMap.put(cName, searchable);
- }
- }
- }
-
- // record the final values as a coherent pair
- synchronized (SearchableInfo.class) {
- sSearchablesList = newSearchablesList;
- sSearchablesMap = newSearchablesMap;
- }
- }
-
- /**
- * Constructor
- *
- * Given a ComponentName, get the searchability info
- * and build a local copy of it. Use the factory, not this.
- *
- * @param context runtime context
- * @param attr The attribute set we found in the XML file, contains the values that are used to
- * construct the object.
- * @param cName The component name of the searchable activity
- */
- private SearchableInfo(Context context, AttributeSet attr, final ComponentName cName) {
- // initialize as an "unsearchable" object
- mSearchable = false;
- mSearchActivity = cName;
-
- // to access another activity's resources, I need its context.
- // BE SURE to release the cache sometime after construction - it's a large object to hold
- mCacheActivityContext = getActivityContext(context);
- if (mCacheActivityContext != null) {
- TypedArray a = mCacheActivityContext.obtainStyledAttributes(attr,
- com.android.internal.R.styleable.Searchable);
- mSearchMode = a.getInt(com.android.internal.R.styleable.Searchable_searchMode, 0);
- mLabelId = a.getResourceId(com.android.internal.R.styleable.Searchable_label, 0);
- mHintId = a.getResourceId(com.android.internal.R.styleable.Searchable_hint, 0);
- mIconId = a.getResourceId(com.android.internal.R.styleable.Searchable_icon, 0);
- mSearchButtonText = a.getResourceId(
- com.android.internal.R.styleable.Searchable_searchButtonText, 0);
- mSearchInputType = a.getInt(com.android.internal.R.styleable.Searchable_inputType,
- InputType.TYPE_CLASS_TEXT |
- InputType.TYPE_TEXT_FLAG_SEARCH |
- InputType.TYPE_TEXT_VARIATION_NORMAL);
-
- setSearchModeFlags();
- if (DBG_INHIBIT_SUGGESTIONS == 0) {
- mSuggestAuthority = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestAuthority);
- mSuggestPath = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestPath);
- mSuggestSelection = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestSelection);
- mSuggestIntentAction = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestIntentAction);
- mSuggestIntentData = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestIntentData);
- }
- mVoiceSearchMode =
- a.getInt(com.android.internal.R.styleable.Searchable_voiceSearchMode, 0);
- // TODO this didn't work - came back zero from YouTube
- mVoiceLanguageModeId =
- a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguageModel, 0);
- mVoicePromptTextId =
- a.getResourceId(com.android.internal.R.styleable.Searchable_voicePromptText, 0);
- mVoiceLanguageId =
- a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguage, 0);
- mVoiceMaxResults =
- a.getInt(com.android.internal.R.styleable.Searchable_voiceMaxResults, 0);
-
- a.recycle();
-
- // get package info for suggestions provider (if any)
- if (mSuggestAuthority != null) {
- ProviderInfo pi =
- context.getPackageManager().resolveContentProvider(mSuggestAuthority,
- 0);
- if (pi != null) {
- mSuggestProviderPackage = pi.packageName;
- }
- }
- }
-
- // for now, implement some form of rules - minimal data
- if (mLabelId != 0) {
- mSearchable = true;
- } else {
- // Provide some help for developers instead of just silently discarding
- Log.w(LOG_TAG, "Insufficient metadata to configure searchability for " +
- cName.flattenToShortString());
- }
- }
-
- /**
- * Convert searchmode to flags.
- */
- private void setSearchModeFlags() {
- mBadgeLabel = (0 != (mSearchMode & 4));
- mBadgeIcon = (0 != (mSearchMode & 8)) && (mIconId != 0);
- mQueryRewriteFromData = (0 != (mSearchMode & 0x10));
- mQueryRewriteFromText = (0 != (mSearchMode & 0x20));
- }
-
- /**
- * Private class used to hold the "action key" configuration
- */
- public class ActionKeyInfo implements Parcelable {
-
- public int mKeyCode = 0;
- public String mQueryActionMsg;
- public String mSuggestActionMsg;
- public String mSuggestActionMsgColumn;
- private ActionKeyInfo mNext;
-
- /**
- * Create one object using attributeset as input data.
- * @param context runtime context
- * @param attr The attribute set we found in the XML file, contains the values that are used to
- * construct the object.
- * @param next We'll build these up using a simple linked list (since there are usually
- * just zero or one).
- */
- public ActionKeyInfo(Context context, AttributeSet attr, ActionKeyInfo next) {
- TypedArray a = mCacheActivityContext.obtainStyledAttributes(attr,
- com.android.internal.R.styleable.SearchableActionKey);
-
- mKeyCode = a.getInt(
- com.android.internal.R.styleable.SearchableActionKey_keycode, 0);
- mQueryActionMsg = a.getString(
- com.android.internal.R.styleable.SearchableActionKey_queryActionMsg);
- if (DBG_INHIBIT_SUGGESTIONS == 0) {
- mSuggestActionMsg = a.getString(
- com.android.internal.R.styleable.SearchableActionKey_suggestActionMsg);
- mSuggestActionMsgColumn = a.getString(
- com.android.internal.R.styleable.SearchableActionKey_suggestActionMsgColumn);
- }
- a.recycle();
-
- // initialize any other fields
- mNext = next;
-
- // sanity check. must have at least one action message, or invalidate the object.
- if ((mQueryActionMsg == null) &&
- (mSuggestActionMsg == null) &&
- (mSuggestActionMsgColumn == null)) {
- mKeyCode = 0;
- }
- }
-
- /**
- * Instantiate a new ActionKeyInfo from the data in a Parcel that was
- * previously written with {@link #writeToParcel(Parcel, int)}.
- *
- * @param in The Parcel containing the previously written ActionKeyInfo,
- * positioned at the location in the buffer where it was written.
- * @param next The value to place in mNext, creating a linked list
- */
- public ActionKeyInfo(Parcel in, ActionKeyInfo next) {
- mKeyCode = in.readInt();
- mQueryActionMsg = in.readString();
- mSuggestActionMsg = in.readString();
- mSuggestActionMsgColumn = in.readString();
- mNext = next;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mKeyCode);
- dest.writeString(mQueryActionMsg);
- dest.writeString(mSuggestActionMsg);
- dest.writeString(mSuggestActionMsgColumn);
- }
- }
-
- /**
- * If any action keys were defined for this searchable activity, look up and return.
- *
- * @param keyCode The key that was pressed
- * @return Returns the ActionKeyInfo record, or null if none defined
- */
- public ActionKeyInfo findActionKey(int keyCode) {
- ActionKeyInfo info = mActionKeyList;
- while (info != null) {
- if (info.mKeyCode == keyCode) {
- return info;
- }
- info = info.mNext;
- }
- return null;
- }
-
- /**
- * Get the metadata for a given activity
- *
- * TODO: clean up where we return null vs. where we throw exceptions.
- *
- * @param context runtime context
- * @param xml XML parser for reading attributes
- * @param cName The component name of the searchable activity
- *
- * @result A completely constructed SearchableInfo, or null if insufficient XML data for it
- */
- private static SearchableInfo getActivityMetaData(Context context, XmlPullParser xml,
- final ComponentName cName) {
- SearchableInfo result = null;
-
- // in order to use the attributes mechanism, we have to walk the parser
- // forward through the file until it's reading the tag of interest.
- try {
- int tagType = xml.next();
- while (tagType != XmlPullParser.END_DOCUMENT) {
- if (tagType == XmlPullParser.START_TAG) {
- if (xml.getName().equals(MD_XML_ELEMENT_SEARCHABLE)) {
- AttributeSet attr = Xml.asAttributeSet(xml);
- if (attr != null) {
- result = new SearchableInfo(context, attr, cName);
- // if the constructor returned a bad object, exit now.
- if (! result.mSearchable) {
- return null;
- }
- }
- } else if (xml.getName().equals(MD_XML_ELEMENT_SEARCHABLE_ACTION_KEY)) {
- if (result == null) {
- // Can't process an embedded element if we haven't seen the enclosing
- return null;
- }
- AttributeSet attr = Xml.asAttributeSet(xml);
- if (attr != null) {
- ActionKeyInfo keyInfo = result.new ActionKeyInfo(context, attr,
- result.mActionKeyList);
- // only add to list if it is was useable
- if (keyInfo.mKeyCode != 0) {
- result.mActionKeyList = keyInfo;
- }
- }
- }
- }
- tagType = xml.next();
- }
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return result;
- }
-
- /**
- * Return the "label" (user-visible name) of this searchable context. This must be
- * accessed using the target (searchable) Activity's resources, not simply the context of the
- * caller.
- *
- * @return Returns the resource Id
- */
- public int getLabelId() {
- return mLabelId;
- }
-
- /**
- * Return the resource Id of the hint text. This must be
- * accessed using the target (searchable) Activity's resources, not simply the context of the
- * caller.
- *
- * @return Returns the resource Id, or 0 if not specified by this package.
- */
- public int getHintId() {
- return mHintId;
- }
-
- /**
- * Return the icon Id specified by the Searchable_icon meta-data entry. This must be
- * accessed using the target (searchable) Activity's resources, not simply the context of the
- * caller.
- *
- * @return Returns the resource id.
- */
- public int getIconId() {
- return mIconId;
- }
-
- /**
- * @return true if android:voiceSearchMode="showVoiceSearchButton"
- */
- public boolean getVoiceSearchEnabled() {
- return 0 != (mVoiceSearchMode & VOICE_SEARCH_SHOW_BUTTON);
- }
-
- /**
- * @return true if android:voiceSearchMode="launchWebSearch"
- */
- public boolean getVoiceSearchLaunchWebSearch() {
- return 0 != (mVoiceSearchMode & VOICE_SEARCH_LAUNCH_WEB_SEARCH);
- }
-
- /**
- * @return true if android:voiceSearchMode="launchRecognizer"
- */
- public boolean getVoiceSearchLaunchRecognizer() {
- return 0 != (mVoiceSearchMode & VOICE_SEARCH_LAUNCH_RECOGNIZER);
- }
-
- /**
- * @return the resource Id of the language model string, if specified in the searchable
- * activity's metadata, or 0 if not specified.
- */
- public int getVoiceLanguageModeId() {
- return mVoiceLanguageModeId;
- }
-
- /**
- * @return the resource Id of the voice prompt text string, if specified in the searchable
- * activity's metadata, or 0 if not specified.
- */
- public int getVoicePromptTextId() {
- return mVoicePromptTextId;
- }
-
- /**
- * @return the resource Id of the spoken langauge, if specified in the searchable
- * activity's metadata, or 0 if not specified.
- */
- public int getVoiceLanguageId() {
- return mVoiceLanguageId;
- }
-
- /**
- * @return the max results count, if specified in the searchable
- * activity's metadata, or 0 if not specified.
- */
- public int getVoiceMaxResults() {
- return mVoiceMaxResults;
- }
-
- /**
- * Return the resource Id of replacement text for the "Search" button.
- *
- * @return Returns the resource Id, or 0 if not specified by this package.
- */
- public int getSearchButtonText() {
- return mSearchButtonText;
- }
-
- /**
- * Return the input type as specified in the searchable attributes. This will default to
- * InputType.TYPE_CLASS_TEXT if not specified (which is appropriate for free text input).
- *
- * @return the input type
- */
- public int getInputType() {
- return mSearchInputType;
- }
-
- /**
- * Return the list of searchable activities, for use in the drop-down.
- */
- public static ArrayList<SearchableInfo> getSearchablesList() {
- synchronized (SearchableInfo.class) {
- ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(sSearchablesList);
- return result;
- }
- }
-
- /**
- * Support for parcelable and aidl operations.
- */
- public static final Parcelable.Creator<SearchableInfo> CREATOR
- = new Parcelable.Creator<SearchableInfo>() {
- public SearchableInfo createFromParcel(Parcel in) {
- return new SearchableInfo(in);
- }
-
- public SearchableInfo[] newArray(int size) {
- return new SearchableInfo[size];
- }
- };
-
- /**
- * Instantiate a new SearchableInfo from the data in a Parcel that was
- * previously written with {@link #writeToParcel(Parcel, int)}.
- *
- * @param in The Parcel containing the previously written SearchableInfo,
- * positioned at the location in the buffer where it was written.
- */
- public SearchableInfo(Parcel in) {
- mSearchable = in.readInt() != 0;
- mLabelId = in.readInt();
- mSearchActivity = ComponentName.readFromParcel(in);
- mHintId = in.readInt();
- mSearchMode = in.readInt();
- mIconId = in.readInt();
- mSearchButtonText = in.readInt();
- mSearchInputType = in.readInt();
- setSearchModeFlags();
-
- mSuggestAuthority = in.readString();
- mSuggestPath = in.readString();
- mSuggestSelection = in.readString();
- mSuggestIntentAction = in.readString();
- mSuggestIntentData = in.readString();
-
- mActionKeyList = null;
- int count = in.readInt();
- while (count-- > 0) {
- mActionKeyList = new ActionKeyInfo(in, mActionKeyList);
- }
-
- mSuggestProviderPackage = in.readString();
-
- mVoiceSearchMode = in.readInt();
- mVoiceLanguageModeId = in.readInt();
- mVoicePromptTextId = in.readInt();
- mVoiceLanguageId = in.readInt();
- mVoiceMaxResults = in.readInt();
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mSearchable ? 1 : 0);
- dest.writeInt(mLabelId);
- mSearchActivity.writeToParcel(dest, flags);
- dest.writeInt(mHintId);
- dest.writeInt(mSearchMode);
- dest.writeInt(mIconId);
- dest.writeInt(mSearchButtonText);
- dest.writeInt(mSearchInputType);
-
- dest.writeString(mSuggestAuthority);
- dest.writeString(mSuggestPath);
- dest.writeString(mSuggestSelection);
- dest.writeString(mSuggestIntentAction);
- dest.writeString(mSuggestIntentData);
-
- // This is usually a very short linked list so we'll just pre-count it
- ActionKeyInfo nextKeyInfo = mActionKeyList;
- int count = 0;
- while (nextKeyInfo != null) {
- ++count;
- nextKeyInfo = nextKeyInfo.mNext;
- }
- dest.writeInt(count);
- // Now write count of 'em
- nextKeyInfo = mActionKeyList;
- while (count-- > 0) {
- nextKeyInfo.writeToParcel(dest, flags);
- }
-
- dest.writeString(mSuggestProviderPackage);
-
- dest.writeInt(mVoiceSearchMode);
- dest.writeInt(mVoiceLanguageModeId);
- dest.writeInt(mVoicePromptTextId);
- dest.writeInt(mVoiceLanguageId);
- dest.writeInt(mVoiceMaxResults);
- }
-}
diff --git a/core/java/android/server/search/package.html b/core/java/android/server/search/package.html
deleted file mode 100644
index c9f96a6..0000000
--- a/core/java/android/server/search/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>