diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-02-10 15:44:00 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-02-10 15:44:00 -0800 |
commit | d24b8183b93e781080b2c16c487e60d51c12da31 (patch) | |
tree | fbb89154858984eb8e41556da7e9433040d55cd4 /core/java/android/server | |
parent | f1e484acb594a726fb57ad0ae4cfe902c7f35858 (diff) | |
download | frameworks_base-d24b8183b93e781080b2c16c487e60d51c12da31.zip frameworks_base-d24b8183b93e781080b2c16c487e60d51c12da31.tar.gz frameworks_base-d24b8183b93e781080b2c16c487e60d51c12da31.tar.bz2 |
auto import from //branches/cupcake/...@130745
Diffstat (limited to 'core/java/android/server')
-rw-r--r-- | core/java/android/server/BluetoothA2dpService.java | 36 | ||||
-rw-r--r-- | core/java/android/server/BluetoothDeviceService.java | 337 | ||||
-rw-r--r-- | core/java/android/server/BluetoothEventLoop.java | 93 | ||||
-rw-r--r-- | core/java/android/server/checkin/CheckinProvider.java | 388 | ||||
-rw-r--r-- | core/java/android/server/checkin/FallbackCheckinService.java | 49 | ||||
-rw-r--r-- | core/java/android/server/checkin/package.html | 5 | ||||
-rw-r--r-- | core/java/android/server/search/SearchableInfo.java | 94 |
7 files changed, 234 insertions, 768 deletions
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 8486e4b..58f9491 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -55,6 +55,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { 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; @@ -136,10 +137,28 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { BluetoothA2dp.STATE_DISCONNECTED)); } } + mAudioManager.setParameter(BLUETOOTH_ENABLED, "true"); } private synchronized void onBluetoothDisable() { - mAudioDevices = null; + 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) { @@ -289,6 +308,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { } } + updateState(path, BluetoothA2dp.STATE_CONNECTING); mAudioManager.setParameter(A2DP_SINK_ADDRESS, lookupAddress(path)); mAudioManager.setBluetoothA2dpOn(true); updateState(path, BluetoothA2dp.STATE_CONNECTED); @@ -309,6 +329,11 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { 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; @@ -349,6 +374,15 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { 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); + } } } diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 3ce34c3..d149761 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -91,8 +91,6 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { mIsDiscovering = false; mEventLoop = new BluetoothEventLoop(mContext, this); registerForAirplaneMode(); - - disableEsco(); // TODO: enable eSCO support once its fully supported } private native void initializeNativeDataNative(); @@ -130,10 +128,21 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } 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; - Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON, 0); + persistBluetoothOnSetting(false); mIsDiscovering = false; - Intent intent = new Intent(BluetoothIntent.DISABLED_ACTION); + intent = new Intent(BluetoothIntent.DISABLED_ACTION); mContext.sendBroadcast(intent, BLUETOOTH_PERM); return true; } @@ -202,18 +211,27 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { if (res) { mIsEnabled = true; - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.BLUETOOTH_ON, 1); + 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(); @@ -288,10 +306,10 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { return state.intValue(); } - public synchronized String[] listBonds() { + 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() == BluetoothDevice.BOND_BONDED) { + if (e.getValue().intValue() == state) { result.add(e.getKey()); } } @@ -353,18 +371,6 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } private native boolean setNameNative(String name); - public synchronized String getMajorClass() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return getMajorClassNative(); - } - private native String getMajorClassNative(); - - public synchronized String getMinorClass() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return getMinorClassNative(); - } - private native String getMinorClassNative(); - /** * Returns the user-friendly name of a remote device. This value is * retrned from our local cache, which is updated during device discovery. @@ -386,24 +392,6 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { /* pacakge */ native String getAdapterPathNative(); - /** - * Initiate a remote-device-discovery procedure. This procedure may be - * canceled by calling {@link #stopDiscovery}. Remote-device discoveries - * are returned as intents - * <p> - * Typically, when a remote device is found, your - * android.bluetooth.DiscoveryEventNotifier#notifyRemoteDeviceFound - * method will be invoked, and subsequently, your - * android.bluetooth.RemoteDeviceEventNotifier#notifyRemoteNameUpdated - * will tell you the user-friendly name of the remote device. However, - * it is possible that the name update may fail for various reasons, so you - * should display the device's Bluetooth address as soon as you get a - * notifyRemoteDeviceFound event, and update the name when you get the - * remote name. - * - * @return true if discovery has started, - * false otherwise. - */ public synchronized boolean startDiscovery(boolean resolveNames) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); @@ -411,12 +399,6 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } private native boolean startDiscoveryNative(boolean resolveNames); - /** - * Cancel a remote-device discovery. - * - * Note: you may safely call this method even when discovery has not been - * started. - */ public synchronized boolean cancelDiscovery() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); @@ -492,171 +474,23 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } private native boolean isConnectedNative(String address); - /** - * Detetermines whether this device is connectable (that is, whether remote - * devices can connect to it.) - * <p> - * Note: A Bluetooth adapter has separate connectable and discoverable - * states, and you could have any combination of those. Although - * any combination is possible (such as discoverable but not - * connectable), we restrict the possible combinations to one of - * three possibilities: discoverable and connectable, connectable - * but not discoverable, and neither connectable nor discoverable. - * - * @return true if this adapter is connectable - * false otherwise - * - * @see #isDiscoverable - * @see #getMode - * @see #setMode - */ - public synchronized boolean isConnectable() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return isConnectableNative(); - } - private native boolean isConnectableNative(); - - /** - * Detetermines whether this device is discoverable. - * - * Note: a Bluetooth adapter has separate connectable and discoverable - * states, and you could have any combination of those. Although - * any combination is possible (such as discoverable but not - * connectable), we restrict the possible combinations to one of - * three possibilities: discoverable and connectable, connectable - * but not discoverable, and neither connectable nor discoverable. - * - * @return true if this adapter is discoverable - * false otherwise - * - * @see #isConnectable - * @see #getMode - * @see #setMode - */ - public synchronized boolean isDiscoverable() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return isDiscoverableNative(); - } - private native boolean isDiscoverableNative(); - - /** - * Determines which one of three modes this adapter is in: discoverable and - * connectable, not discoverable but connectable, or neither. - * - * @return Mode enumeration containing the current mode. - * - * @see #setMode - */ - public synchronized int getMode() { + public synchronized int getScanMode() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - String mode = getModeNative(); - if (mode == null) { - return BluetoothDevice.MODE_UNKNOWN; - } - if (mode.equalsIgnoreCase("off")) { - return BluetoothDevice.MODE_OFF; - } - else if (mode.equalsIgnoreCase("connectable")) { - return BluetoothDevice.MODE_CONNECTABLE; - } - else if (mode.equalsIgnoreCase("discoverable")) { - return BluetoothDevice.MODE_DISCOVERABLE; - } - else { - return BluetoothDevice.MODE_UNKNOWN; - } + return bluezStringToScanMode(getModeNative()); } private native String getModeNative(); - /** - * Set the discoverability and connectability mode of this adapter. The - * possibilities are discoverable and connectable (MODE_DISCOVERABLE), - * connectable but not discoverable (MODE_CONNECTABLE), and neither - * (MODE_OFF). - * - * Note: MODE_OFF does not mean that the adapter is physically off. It - * may be neither discoverable nor connectable, but it could still - * initiate outgoing connections, or could participate in a - * connection initiated by a remote device before its mode was set - * to MODE_OFF. - * - * @param mode the new mode - * @see #getMode - */ - public synchronized boolean setMode(int mode) { + public synchronized boolean setScanMode(int mode) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - switch (mode) { - case BluetoothDevice.MODE_OFF: - return setModeNative("off"); - case BluetoothDevice.MODE_CONNECTABLE: - return setModeNative("connectable"); - case BluetoothDevice.MODE_DISCOVERABLE: - return setModeNative("discoverable"); + String bluezMode = scanModeToBluezString(mode); + if (bluezMode != null) { + return setModeNative(bluezMode); } return false; } private native boolean setModeNative(String mode); - /** - * Retrieves the alias of a remote device. The alias is a local feature, - * and allows us to associate a name with a remote device that is different - * from that remote device's user-friendly name. The remote device knows - * nothing about this. The alias can be changed with - * {@link #setRemoteAlias}, and it may be removed with - * {@link #clearRemoteAlias} - * - * @param address Bluetooth address of remote device. - * - * @return The alias of the remote device. - */ - public synchronized String getRemoteAlias(String address) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - if (!BluetoothDevice.checkBluetoothAddress(address)) { - return null; - } - return getRemoteAliasNative(address); - } - private native String getRemoteAliasNative(String address); - - /** - * Changes the alias of a remote device. The alias is a local feature, - * from that remote device's user-friendly name. The remote device knows - * nothing about this. The alias can be retrieved with - * {@link #getRemoteAlias}, and it may be removed with - * {@link #clearRemoteAlias}. - * - * @param address Bluetooth address of remote device - * @param alias Alias for the remote device - */ - public synchronized boolean setRemoteAlias(String address, String alias) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH_ADMIN permission"); - if (alias == null || !BluetoothDevice.checkBluetoothAddress(address)) { - return false; - } - return setRemoteAliasNative(address, alias); - } - private native boolean setRemoteAliasNative(String address, String alias); - - /** - * Removes the alias of a remote device. The alias is a local feature, - * from that remote device's user-friendly name. The remote device knows - * nothing about this. The alias can be retrieved with - * {@link #getRemoteAlias}. - * - * @param address Bluetooth address of remote device - */ - public synchronized boolean clearRemoteAlias(String address) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH_ADMIN permission"); - if (!BluetoothDevice.checkBluetoothAddress(address)) { - return false; - } - return clearRemoteAliasNative(address); - } - private native boolean clearRemoteAliasNative(String address); - public synchronized boolean disconnectRemoteDeviceAcl(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); @@ -699,7 +533,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED, - BluetoothDevice.UNBOND_REASON_CANCELLED); + BluetoothDevice.UNBOND_REASON_AUTH_CANCELED); cancelBondingProcessNative(address); return true; } @@ -717,7 +551,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public synchronized String[] listBonds() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return mBondState.listBonds(); + return mBondState.listInState(BluetoothDevice.BOND_BONDED); } public synchronized int getBondState(String address) { @@ -919,69 +753,6 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private native String lastUsedNative(String address); /** - * Gets the major device class of the specified device. - * Example: "computer" - * - * Note: This is simply a string desciption of the major class of the - * device-class information, which is returned as a 32-bit value - * during device discovery. - * - * @param address The Bluetooth address of the remote device. - * - * @return remote-device major class - * - * @see #getRemoteClass - */ - public synchronized String getRemoteMajorClass(String address) { - if (!BluetoothDevice.checkBluetoothAddress(address)) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return null; - } - return getRemoteMajorClassNative(address); - } - private native String getRemoteMajorClassNative(String address); - - /** - * Gets the minor device class of the specified device. - * Example: "laptop" - * - * Note: This is simply a string desciption of the minor class of the - * device-class information, which is returned as a 32-bit value - * during device discovery. - * - * @param address The Bluetooth address of the remote device. - * - * @return remote-device minor class - * - * @see #getRemoteClass - */ - public synchronized String getRemoteMinorClass(String address) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - if (!BluetoothDevice.checkBluetoothAddress(address)) { - return null; - } - return getRemoteMinorClassNative(address); - } - private native String getRemoteMinorClassNative(String address); - - /** - * Gets the service classes of the specified device. - * Example: ["networking", "object transfer"] - * - * @return a String array with the descriptions of the service classes. - * - * @see #getRemoteClass - */ - public synchronized String[] getRemoteServiceClasses(String address) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - if (!BluetoothDevice.checkBluetoothAddress(address)) { - return null; - } - return getRemoteServiceClassesNative(address); - } - private native String[] getRemoteServiceClassesNative(String address); - - /** * Gets the remote major, minor, and service classes encoded as a 32-bit * integer. * @@ -1188,16 +959,6 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { Settings.System.AIRPLANE_MODE_ON, 0) == 1; } - private static final String DISABLE_ESCO_PATH = "/sys/module/sco/parameters/disable_esco"; - private static void disableEsco() { - try { - FileWriter file = new FileWriter(DISABLE_ESCO_PATH); - file.write("Y"); - file.close(); - } catch (FileNotFoundException e) { - } catch (IOException e) {} - } - @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mIsEnabled) { @@ -1248,6 +1009,34 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { 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 index 4f63f98..0f60fae 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -16,6 +16,7 @@ package android.server; +import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothError; @@ -114,9 +115,7 @@ class BluetoothEventLoop { public synchronized void stop() { if (mThread != null) { - mInterrupted = true; - try { mThread.join(); mThread = null; @@ -130,104 +129,86 @@ class BluetoothEventLoop { return mThread != null; } - public void onModeChanged(String mode) { - Intent intent = new Intent(BluetoothIntent.MODE_CHANGED_ACTION); - int intMode = BluetoothDevice.MODE_UNKNOWN; - if (mode.equalsIgnoreCase("off")) { - intMode = BluetoothDevice.MODE_OFF; - } - else if (mode.equalsIgnoreCase("connectable")) { - intMode = BluetoothDevice.MODE_CONNECTABLE; - } - else if (mode.equalsIgnoreCase("discoverable")) { - intMode = BluetoothDevice.MODE_DISCOVERABLE; + /*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); } - intent.putExtra(BluetoothIntent.MODE, intMode); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - public void onDiscoveryStarted() { + private void onDiscoveryStarted() { mBluetoothService.setIsDiscovering(true); Intent intent = new Intent(BluetoothIntent.DISCOVERY_STARTED_ACTION); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - public void onDiscoveryCompleted() { + private void onDiscoveryCompleted() { mBluetoothService.setIsDiscovering(false); Intent intent = new Intent(BluetoothIntent.DISCOVERY_COMPLETED_ACTION); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - public void onPairingRequest() { + private void onPairingRequest() { Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); } - public void onPairingCancel() { + private void onPairingCancel() { Intent intent = new Intent(BluetoothIntent.PAIRING_CANCEL_ACTION); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); } - public void onRemoteDeviceFound(String address, int deviceClass, short rssi) { + 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); } - public void onRemoteDeviceDisappeared(String address) { + private void onRemoteDeviceDisappeared(String address) { Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISAPPEARED_ACTION); intent.putExtra(BluetoothIntent.ADDRESS, address); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - public void onRemoteClassUpdated(String address, int deviceClass) { + 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); } - public void onRemoteDeviceConnected(String address) { + private void onRemoteDeviceConnected(String address) { Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION); intent.putExtra(BluetoothIntent.ADDRESS, address); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - public void onRemoteDeviceDisconnectRequested(String address) { + 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); } - public void onRemoteDeviceDisconnected(String address) { + private void onRemoteDeviceDisconnected(String address) { Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISCONNECTED_ACTION); intent.putExtra(BluetoothIntent.ADDRESS, address); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - public void onRemoteNameUpdated(String address, String name) { + 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); } - public void onRemoteNameFailed(String address) { + private void onRemoteNameFailed(String address) { Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_FAILED_ACTION); intent.putExtra(BluetoothIntent.ADDRESS, address); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - public void onRemoteNameChanged(String address, String name) { + 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); } - public void onRemoteAliasChanged(String address, String alias) { - Intent intent = new Intent(BluetoothIntent.REMOTE_ALIAS_CHANGED_ACTION); - intent.putExtra(BluetoothIntent.ADDRESS, address); - intent.putExtra(BluetoothIntent.ALIAS, alias); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - } - public void onRemoteAliasCleared(String address) { - Intent intent = new Intent(BluetoothIntent.REMOTE_ALIAS_CLEARED_ACTION); - intent.putExtra(BluetoothIntent.ADDRESS, address); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - } private void onCreateBondingResult(String address, int result) { address = address.toUpperCase(); @@ -239,23 +220,23 @@ class BluetoothEventLoop { } } - public void onBondingCreated(String address) { + private void onBondingCreated(String address) { mBluetoothService.getBondState().setBondState(address.toUpperCase(), BluetoothDevice.BOND_BONDED); } - public void onBondingRemoved(String address) { + private void onBondingRemoved(String address) { mBluetoothService.getBondState().setBondState(address.toUpperCase(), BluetoothDevice.BOND_NOT_BONDED, BluetoothDevice.UNBOND_REASON_REMOVED); } - public void onNameChanged(String name) { + private void onNameChanged(String name) { Intent intent = new Intent(BluetoothIntent.NAME_CHANGED_ACTION); intent.putExtra(BluetoothIntent.NAME, name); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - public void onPasskeyAgentRequest(String address, int nativeData) { + private void onPasskeyAgentRequest(String address, int nativeData) { address = address.toUpperCase(); mPasskeyAgentRequestData.put(address, new Integer(nativeData)); @@ -284,14 +265,36 @@ class BluetoothEventLoop { mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); } - public void onPasskeyAgentCancel(String address) { + 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_CANCELLED); + 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) { diff --git a/core/java/android/server/checkin/CheckinProvider.java b/core/java/android/server/checkin/CheckinProvider.java deleted file mode 100644 index 86ece4a..0000000 --- a/core/java/android/server/checkin/CheckinProvider.java +++ /dev/null @@ -1,388 +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.checkin; - -import android.content.ContentProvider; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.Context; -import android.content.pm.PackageManager; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteQueryBuilder; -import android.net.Uri; -import android.os.Environment; -import android.provider.BaseColumns; -import android.provider.Checkin; -import android.util.Log; - -import java.io.File; - -/** - * Content provider for the database used to store events and statistics - * while they wait to be uploaded by the checkin service. - */ -public class CheckinProvider extends ContentProvider { - /** Class identifier for logging. */ - private static final String TAG = "CheckinProvider"; - - /** Filename of database (in /data directory). */ - private static final String DATABASE_FILENAME = "checkin.db"; - - /** Version of database schema. */ - private static final int DATABASE_VERSION = 1; - - /** Maximum number of events recorded. */ - private static final int EVENT_LIMIT = 1000; - - /** Maximum size of individual event data. */ - private static final int EVENT_SIZE = 8192; - - /** Maximum number of crashes recorded. */ - private static final int CRASH_LIMIT = 25; - - /** Maximum size of individual crashes recorded. */ - private static final int CRASH_SIZE = 16384; - - /** Permission required for access to the 'properties' database. */ - private static final String PROPERTIES_PERMISSION = - "android.permission.ACCESS_CHECKIN_PROPERTIES"; - - /** Lock for stats read-modify-write update cycle (see {@link #insert}). */ - private final Object mStatsLock = new Object(); - - /** The underlying SQLite database. */ - private SQLiteOpenHelper mOpenHelper; - - private static class OpenHelper extends SQLiteOpenHelper { - public OpenHelper(Context context) { - super(context, DATABASE_FILENAME, null, DATABASE_VERSION); - - // The database used to live in /data/checkin.db. - File oldLocation = Environment.getDataDirectory(); - File old = new File(oldLocation, DATABASE_FILENAME); - File file = context.getDatabasePath(DATABASE_FILENAME); - - // Try to move the file to the new location. - // TODO: Remove this code before shipping. - if (old.exists() && !file.exists() && !old.renameTo(file)) { - Log.e(TAG, "Can't rename " + old + " to " + file); - } - if (old.exists() && !old.delete()) { - // Clean up the old data file in any case. - Log.e(TAG, "Can't remove " + old); - } - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + Checkin.Events.TABLE_NAME + " (" + - BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - Checkin.Events.TAG + " TEXT NOT NULL," + - Checkin.Events.VALUE + " TEXT DEFAULT \"\"," + - Checkin.Events.DATE + " INTEGER NOT NULL)"); - - db.execSQL("CREATE INDEX events_index ON " + - Checkin.Events.TABLE_NAME + " (" + - Checkin.Events.TAG + ")"); - - db.execSQL("CREATE TABLE " + Checkin.Stats.TABLE_NAME + " (" + - BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - Checkin.Stats.TAG + " TEXT UNIQUE," + - Checkin.Stats.COUNT + " INTEGER DEFAULT 0," + - Checkin.Stats.SUM + " REAL DEFAULT 0.0)"); - - db.execSQL("CREATE TABLE " + Checkin.Crashes.TABLE_NAME + " (" + - BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - Checkin.Crashes.DATA + " TEXT NOT NULL," + - Checkin.Crashes.LOGS + " TEXT)"); - - db.execSQL("CREATE TABLE " + Checkin.Properties.TABLE_NAME + " (" + - BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - Checkin.Properties.TAG + " TEXT UNIQUE ON CONFLICT REPLACE," - + Checkin.Properties.VALUE + " TEXT DEFAULT \"\")"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int old, int version) { - db.execSQL("DROP TABLE IF EXISTS " + Checkin.Events.TABLE_NAME); - db.execSQL("DROP TABLE IF EXISTS " + Checkin.Stats.TABLE_NAME); - db.execSQL("DROP TABLE IF EXISTS " + Checkin.Crashes.TABLE_NAME); - db.execSQL("DROP TABLE IF EXISTS " + Checkin.Properties.TABLE_NAME); - onCreate(db); - } - } - - @Override public boolean onCreate() { - mOpenHelper = new OpenHelper(getContext()); - return true; - } - - @Override - public Cursor query(Uri uri, String[] select, - String where, String[] args, String sort) { - checkPermissions(uri); - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - qb.setTables(uri.getPathSegments().get(0)); - if (uri.getPathSegments().size() == 2) { - qb.appendWhere("_id=" + ContentUris.parseId(uri)); - } else if (uri.getPathSegments().size() != 1) { - throw new IllegalArgumentException("Invalid query URI: " + uri); - } - - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - Cursor cursor = qb.query(db, select, where, args, null, null, sort); - cursor.setNotificationUri(getContext().getContentResolver(), uri); - return cursor; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - checkPermissions(uri); - if (uri.getPathSegments().size() != 1) { - throw new IllegalArgumentException("Invalid insert URI: " + uri); - } - - long id; - String table = uri.getPathSegments().get(0); - if (Checkin.Events.TABLE_NAME.equals(table)) { - id = insertEvent(values); - } else if (Checkin.Stats.TABLE_NAME.equals(table)) { - id = insertStats(values); - } else if (Checkin.Crashes.TABLE_NAME.equals(table)) { - id = insertCrash(values); - } else { - id = mOpenHelper.getWritableDatabase().insert(table, null, values); - } - - if (id < 0) { - return null; - } else { - uri = ContentUris.withAppendedId(uri, id); - getContext().getContentResolver().notifyChange(uri, null); - return uri; - } - } - - /** - * Insert an entry into the events table. - * Trims old events from the table to keep the size bounded. - * @param values to insert - * @return the row ID of the new entry - */ - private long insertEvent(ContentValues values) { - String value = values.getAsString(Checkin.Events.VALUE); - if (value != null && value.length() > EVENT_SIZE) { - // Event values are readable text, so they can be truncated. - value = value.substring(0, EVENT_SIZE - 3) + "..."; - values.put(Checkin.Events.VALUE, value); - } - - if (!values.containsKey(Checkin.Events.DATE)) { - values.put(Checkin.Events.DATE, System.currentTimeMillis()); - } - - // TODO: Make this more efficient; don't do it on every insert. - // Also, consider keeping the most recent instance of every tag, - // and possibly update a counter when events are deleted. - - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.execSQL("DELETE FROM " + - Checkin.Events.TABLE_NAME + " WHERE " + - Checkin.Events._ID + " IN (SELECT " + - Checkin.Events._ID + " FROM " + - Checkin.Events.TABLE_NAME + " ORDER BY " + - Checkin.Events.DATE + " DESC LIMIT -1 OFFSET " + - (EVENT_LIMIT - 1) + ")"); - return db.insert(Checkin.Events.TABLE_NAME, null, values); - } - - /** - * Add an entry into the stats table. - * For statistics, instead of just inserting a row into the database, - * we add the count and sum values to the existing values (if any) - * for the specified tag. This must be done with a lock held, - * to avoid a race condition during the read-modify-write update. - * @param values to insert - * @return the row ID of the modified entry - */ - private long insertStats(ContentValues values) { - synchronized (mStatsLock) { - String tag = values.getAsString(Checkin.Stats.TAG); - if (tag == null) { - throw new IllegalArgumentException("Tag required:" + values); - } - - // Look for existing values with this tag. - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - Cursor cursor = db.query(false, - Checkin.Stats.TABLE_NAME, - new String[] { - Checkin.Stats._ID, - Checkin.Stats.COUNT, - Checkin.Stats.SUM - }, - Checkin.Stats.TAG + "=?", - new String[] { tag }, - null, null, null, null /* limit */); - - try { - if (cursor == null || !cursor.moveToNext()) { - // This is a new statistic, insert it directly. - return db.insert(Checkin.Stats.TABLE_NAME, null, values); - } else { - // Depend on SELECT column order to avoid getColumnIndex() - long id = cursor.getLong(0); - int count = cursor.getInt(1); - double sum = cursor.getDouble(2); - - Integer countAdd = values.getAsInteger(Checkin.Stats.COUNT); - if (countAdd != null) count += countAdd.intValue(); - - Double sumAdd = values.getAsDouble(Checkin.Stats.SUM); - if (sumAdd != null) sum += sumAdd.doubleValue(); - - if (count <= 0 && sum == 0.0) { - // Updated to nothing: delete the row! - cursor.deleteRow(); - getContext().getContentResolver().notifyChange( - ContentUris.withAppendedId(Checkin.Stats.CONTENT_URI, id), null); - return -1; - } else { - if (countAdd != null) cursor.updateInt(1, count); - if (sumAdd != null) cursor.updateDouble(2, sum); - cursor.commitUpdates(); - return id; - } - } - } finally { - // Always clean up the cursor. - if (cursor != null) cursor.close(); - } - } - } - - /** - * Add an entry into the crashes table. - * @param values to insert - * @return the row ID of the modified entry - */ - private long insertCrash(ContentValues values) { - try { - int crashSize = values.getAsString(Checkin.Crashes.DATA).length(); - if (crashSize > CRASH_SIZE) { - // The crash is too big. Don't report it, but do log a stat. - Checkin.updateStats(getContext().getContentResolver(), - Checkin.Stats.Tag.CRASHES_TRUNCATED, 1, 0.0); - throw new IllegalArgumentException("Too big: " + crashSize); - } - - // Count the number of crashes reported, even if they roll over. - Checkin.updateStats(getContext().getContentResolver(), - Checkin.Stats.Tag.CRASHES_REPORTED, 1, 0.0); - - // Trim the crashes database, if needed. - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.execSQL("DELETE FROM " + - Checkin.Crashes.TABLE_NAME + " WHERE " + - Checkin.Crashes._ID + " IN (SELECT " + - Checkin.Crashes._ID + " FROM " + - Checkin.Crashes.TABLE_NAME + " ORDER BY " + - Checkin.Crashes._ID + " DESC LIMIT -1 OFFSET " + - (CRASH_LIMIT - 1) + ")"); - - return db.insert(Checkin.Crashes.TABLE_NAME, null, values); - } catch (Throwable t) { - // To avoid an infinite crash-reporting loop, swallow the error. - Log.e("CheckinProvider", "Error inserting crash: " + t); - return -1; - } - } - - // TODO: optimize bulkInsert, especially for stats? - - @Override - public int update(Uri uri, ContentValues values, - String where, String[] args) { - checkPermissions(uri); - if (uri.getPathSegments().size() == 2) { - if (where != null && where.length() > 0) { - throw new UnsupportedOperationException( - "WHERE clause not supported for update: " + uri); - } - where = "_id=" + ContentUris.parseId(uri); - args = null; - } else if (uri.getPathSegments().size() != 1) { - throw new IllegalArgumentException("Invalid update URI: " + uri); - } - - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - int count = db.update(uri.getPathSegments().get(0), values, where, args); - getContext().getContentResolver().notifyChange(uri, null); - return count; - } - - @Override - public int delete(Uri uri, String where, String[] args) { - checkPermissions(uri); - if (uri.getPathSegments().size() == 2) { - if (where != null && where.length() > 0) { - throw new UnsupportedOperationException( - "WHERE clause not supported for delete: " + uri); - } - where = "_id=" + ContentUris.parseId(uri); - args = null; - } else if (uri.getPathSegments().size() != 1) { - throw new IllegalArgumentException("Invalid delete URI: " + uri); - } - - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - int count = db.delete(uri.getPathSegments().get(0), where, args); - getContext().getContentResolver().notifyChange(uri, null); - return count; - } - - @Override - public String getType(Uri uri) { - if (uri.getPathSegments().size() == 1) { - return "vnd.android.cursor.dir/" + uri.getPathSegments().get(0); - } else if (uri.getPathSegments().size() == 2) { - return "vnd.android.cursor.item/" + uri.getPathSegments().get(0); - } else { - throw new IllegalArgumentException("Invalid URI: " + uri); - } - } - - /** - * Make sure the caller has permission to the database. - * @param uri the caller is requesting access to - * @throws SecurityException if the caller is forbidden. - */ - private void checkPermissions(Uri uri) { - if (uri.getPathSegments().size() < 1) { - throw new IllegalArgumentException("Invalid query URI: " + uri); - } - - String table = uri.getPathSegments().get(0); - if (table.equals(Checkin.Properties.TABLE_NAME) && - getContext().checkCallingOrSelfPermission(PROPERTIES_PERMISSION) != - PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Cannot access checkin properties"); - } - } -} diff --git a/core/java/android/server/checkin/FallbackCheckinService.java b/core/java/android/server/checkin/FallbackCheckinService.java deleted file mode 100644 index 65921af..0000000 --- a/core/java/android/server/checkin/FallbackCheckinService.java +++ /dev/null @@ -1,49 +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.checkin; - -import android.os.ICheckinService; -import android.os.RemoteException; -import android.os.IParentalControlCallback; -import com.google.android.net.ParentalControlState; - -/** - * @hide - */ -public final class FallbackCheckinService extends ICheckinService.Stub { - public FallbackCheckinService() { - } - - public void reportCrashSync(byte[] crashData) throws RemoteException { - } - - public void reportCrashAsync(byte[] crashData) throws RemoteException { - } - - public void masterClear() throws RemoteException { - } - - public void getParentalControlState(IParentalControlCallback p) throws RemoteException { - ParentalControlState state = new ParentalControlState(); - state.isEnabled = false; - p.onResult(state); - } - - public void getParentalControlState(IParentalControlCallback p, String requestingApp) - throws android.os.RemoteException { - } -} diff --git a/core/java/android/server/checkin/package.html b/core/java/android/server/checkin/package.html deleted file mode 100644 index 1c9bf9d..0000000 --- a/core/java/android/server/checkin/package.html +++ /dev/null @@ -1,5 +0,0 @@ -<html> -<body> - {@hide} -</body> -</html> diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java index c8f395e..c18675e 100644 --- a/core/java/android/server/search/SearchableInfo.java +++ b/core/java/android/server/search/SearchableInfo.java @@ -86,6 +86,16 @@ public final class SearchableInfo implements Parcelable { 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). */ @@ -420,7 +430,7 @@ public final class SearchableInfo implements Parcelable { mSearchInputType = a.getInt(com.android.internal.R.styleable.Searchable_inputType, InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_SEARCH | - InputType.TYPE_TEXT_VARIATION_SEARCH_STRING); + InputType.TYPE_TEXT_VARIATION_NORMAL); setSearchModeFlags(); if (DBG_INHIBIT_SUGGESTIONS == 0) { @@ -435,6 +445,18 @@ public final class SearchableInfo implements Parcelable { 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) @@ -462,11 +484,6 @@ public final class SearchableInfo implements Parcelable { * Convert searchmode to flags. */ private void setSearchModeFlags() { - // decompose searchMode attribute - // TODO How do I reconcile these hardcoded values with the flag bits defined in - // in attrs.xml? e.g. android.R.id.filterMode = 0x010200a4 instead of just "1" - /* mFilterMode = (0 != (mSearchMode & 1)); */ - /* mQuickStart = (0 != (mSearchMode & 2)); */ mBadgeLabel = (0 != (mSearchMode & 4)); mBadgeIcon = (0 != (mSearchMode & 8)) && (mIconId != 0); mQueryRewriteFromData = (0 != (mSearchMode & 0x10)); @@ -654,6 +671,59 @@ public final class SearchableInfo implements Parcelable { } /** + * @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. @@ -727,6 +797,12 @@ public final class SearchableInfo implements Parcelable { } mSuggestProviderPackage = in.readString(); + + mVoiceSearchMode = in.readInt(); + mVoiceLanguageModeId = in.readInt(); + mVoicePromptTextId = in.readInt(); + mVoiceLanguageId = in.readInt(); + mVoiceMaxResults = in.readInt(); } public int describeContents() { @@ -764,5 +840,11 @@ public final class SearchableInfo implements Parcelable { } dest.writeString(mSuggestProviderPackage); + + dest.writeInt(mVoiceSearchMode); + dest.writeInt(mVoiceLanguageModeId); + dest.writeInt(mVoicePromptTextId); + dest.writeInt(mVoiceLanguageId); + dest.writeInt(mVoiceMaxResults); } } |