diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 | 
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 | 
| commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/server | |
| parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
| download | frameworks_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.java | 412 | ||||
| -rw-r--r-- | core/java/android/server/BluetoothDeviceService.java | 1107 | ||||
| -rw-r--r-- | core/java/android/server/BluetoothEventLoop.java | 373 | ||||
| -rw-r--r-- | core/java/android/server/data/BuildData.java | 89 | ||||
| -rw-r--r-- | core/java/android/server/data/CrashData.java | 145 | ||||
| -rw-r--r-- | core/java/android/server/data/StackTraceElementData.java | 80 | ||||
| -rw-r--r-- | core/java/android/server/data/ThrowableData.java | 138 | ||||
| -rwxr-xr-x | core/java/android/server/data/package.html | 5 | ||||
| -rwxr-xr-x | core/java/android/server/package.html | 5 | ||||
| -rw-r--r-- | core/java/android/server/search/SearchManagerService.java | 156 | ||||
| -rw-r--r-- | core/java/android/server/search/SearchableInfo.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/server/search/SearchableInfo.java | 850 | ||||
| -rw-r--r-- | core/java/android/server/search/package.html | 5 | 
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> | 
