diff options
84 files changed, 2507 insertions, 552 deletions
diff --git a/Android.mk b/Android.mk index bac38024ed36..5dfa58a6ba62 100644 --- a/Android.mk +++ b/Android.mk @@ -125,6 +125,8 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothSap.aidl \ core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \ core/java/android/bluetooth/IBluetoothHeadsetClient.aidl \ + core/java/android/bluetooth/IBluetoothInputHost.aidl \ + core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl \ core/java/android/bluetooth/IBluetoothGatt.aidl \ core/java/android/bluetooth/IBluetoothGattCallback.aidl \ core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \ diff --git a/api/system-current.txt b/api/system-current.txt index 338e87ec23b7..b62196a4a5a6 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -40,6 +40,7 @@ package android { field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD"; field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET"; field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE"; + field public static final java.lang.String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"; field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE"; field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"; field public static final java.lang.String BIND_PRINT_RECOMMENDATION_SERVICE = "android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"; @@ -62,7 +63,7 @@ package android { field public static final java.lang.String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED"; field public static final java.lang.String BODY_SENSORS = "android.permission.BODY_SENSORS"; field public static final java.lang.String BRICK = "android.permission.BRICK"; - field public static final java.lang.String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED"; + field public static final deprecated java.lang.String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED"; field public static final java.lang.String BROADCAST_PACKAGE_REMOVED = "android.permission.BROADCAST_PACKAGE_REMOVED"; field public static final java.lang.String BROADCAST_SMS = "android.permission.BROADCAST_SMS"; field public static final java.lang.String BROADCAST_STICKY = "android.permission.BROADCAST_STICKY"; @@ -196,6 +197,7 @@ package android { field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS"; field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; + field public static final java.lang.String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT"; field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS"; @@ -25760,6 +25762,14 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR; } + public static final class RecommendationRequest.Builder { + ctor public RecommendationRequest.Builder(); + method public android.net.RecommendationRequest build(); + method public android.net.RecommendationRequest.Builder setCurrentRecommendedWifiConfig(android.net.wifi.WifiConfiguration); + method public android.net.RecommendationRequest.Builder setNetworkCapabilities(android.net.NetworkCapabilities); + method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]); + } + public final class RecommendationResult implements android.os.Parcelable { method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration); method public static android.net.RecommendationResult createDoNotConnectRecommendation(); diff --git a/compiled-classes-phone b/compiled-classes-phone index 221d68739366..ec3371e45711 100644 --- a/compiled-classes-phone +++ b/compiled-classes-phone @@ -632,6 +632,7 @@ android.bluetooth.BluetoothAdapter$LeScanCallback android.bluetooth.BluetoothAudioConfig android.bluetooth.BluetoothClass android.bluetooth.BluetoothClass$1 +android.bluetooth.BluetoothCodecConfig android.bluetooth.BluetoothDevice android.bluetooth.BluetoothDevice$1 android.bluetooth.BluetoothDevice$2 diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 8f424676dbe5..857a361788d6 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -509,10 +509,23 @@ class ContextImpl extends Context { * Common-path handling of app data dir creation */ private static File ensurePrivateDirExists(File file) { + return ensurePrivateDirExists(file, 0771, -1); + } + + private static File ensurePrivateCacheDirExists(File file) { + final int gid = UserHandle.getCacheAppGid(Process.myUid()); + return ensurePrivateDirExists(file, 02771, gid); + } + + private static File ensurePrivateDirExists(File file, int mode, int gid) { if (!file.exists()) { + final String path = file.getAbsolutePath(); try { - Os.mkdir(file.getAbsolutePath(), 0771); - Os.chmod(file.getAbsolutePath(), 0771); + Os.mkdir(path, mode); + Os.chmod(path, mode); + if (gid != -1) { + Os.chown(path, -1, gid); + } } catch (ErrnoException e) { if (e.errno == OsConstants.EEXIST) { // We must have raced with someone; that's okay @@ -581,7 +594,7 @@ class ContextImpl extends Context { if (mCacheDir == null) { mCacheDir = new File(getDataDir(), "cache"); } - return ensurePrivateDirExists(mCacheDir); + return ensurePrivateCacheDirExists(mCacheDir); } } @@ -591,7 +604,7 @@ class ContextImpl extends Context { if (mCodeCacheDir == null) { mCodeCacheDir = new File(getDataDir(), "code_cache"); } - return ensurePrivateDirExists(mCodeCacheDir); + return ensurePrivateCacheDirExists(mCodeCacheDir); } } diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index 353c6400ffd7..1165fce3ce0a 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -102,6 +102,27 @@ public final class BluetoothA2dp implements BluetoothProfile { "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED"; /** + * Intent used to broadcast the change in the Audio Codec state of the + * A2DP Source profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_CODEC_CONFIG} - The current codec configuration. </li> + * <li> {@link #EXTRA_PREVIOUS_CODEC_CONFIG} - The previous codec configuration. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently + * connected, otherwise it is not included.</li> + * </ul> + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_CODEC_CONFIG_CHANGED = + "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED"; + + /** * A2DP sink device is streaming music. This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of * {@link #ACTION_PLAYING_STATE_CHANGED} intent. @@ -543,6 +564,54 @@ public final class BluetoothA2dp implements BluetoothProfile { } /** + * Gets the current codec configuration. + * + * @return the current codec configuration + * @hide + */ + public BluetoothCodecConfig getCodecConfig() { + if (DBG) Log.d(TAG, "getCodecConfig"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + return mService.getCodecConfig(); + } + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + } + return null; + } catch (RemoteException e) { + Log.e(TAG, "Error talking to BT service in getCodecConfig()", e); + return null; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** + * Sets the codec configuration preference. + * + * @param codecConfig the codec configuration preference + * @hide + */ + public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) { + if (DBG) Log.d(TAG, "setCodecConfigPreference"); + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { + mService.setCodecConfigPreference(codecConfig); + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return; + } catch (RemoteException e) { + Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e); + return; + } finally { + mServiceLock.readLock().unlock(); + } + } + + /** * Helper for converting a state to a string. * * For debug use only - strings are not internationalized. diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 4a97b078f7bd..f9be3a1d7f0b 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -680,30 +680,7 @@ public final class BluetoothAdapter { } /** - * Performs action based on user action to turn BT ON - * or OFF if BT is in BLE_ON state - */ - private void notifyUserAction(boolean enable) { - try { - mServiceLock.readLock().lock(); - if (mService == null) { - Log.e(TAG, "mService is null"); - return; - } - if (enable) { - mService.onLeServiceUp(); //NA:TODO implementation pending - } else { - mService.onBrEdrDown(); //NA:TODO implementation pending - } - } catch (RemoteException e) { - Log.e(TAG, "", e); - } finally { - mServiceLock.readLock().unlock(); - } - } - - /** - * Turns off Bluetooth LE which was earlier turned on by calling EnableBLE(). + * Turns off Bluetooth LE which was earlier turned on by calling enableBLE(). * * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition * to STATE_OFF and completely shut-down Bluetooth @@ -733,61 +710,50 @@ public final class BluetoothAdapter { if (!isBleScanAlwaysAvailable()) return false; int state = getLeState(); - if (state == BluetoothAdapter.STATE_ON) { - if (DBG) Log.d (TAG, "STATE_ON: shouldn't disable"); - try { - mManagerService.updateBleAppCount(mToken, false); - } catch (RemoteException e) { - Log.e(TAG, "", e); - } - return true; - - } else if (state == BluetoothAdapter.STATE_BLE_ON) { - if (DBG) Log.d (TAG, "STATE_BLE_ON"); - int bleAppCnt = 0; + if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) { + String packageName = ActivityThread.currentPackageName(); + if (DBG) Log.d (TAG, "disableBLE(): de-registering " + packageName); try { - bleAppCnt = mManagerService.updateBleAppCount(mToken, false); + mManagerService.updateBleAppCount(mToken, false, packageName); } catch (RemoteException e) { Log.e(TAG, "", e); } - if (bleAppCnt == 0) { - // Disable only if there are no other clients - notifyUserAction(false); - } return true; } - if (DBG) Log.d (TAG, "STATE_OFF: Already disabled"); + if (DBG) Log.d (TAG, "disableBLE(): Already disabled"); return false; } /** - * Special Applications who want to only turn on Bluetooth Low Energy (BLE) would - * EnableBLE, EnableBLE brings-up Bluetooth so that application can access - * only LE related feature (Bluetooth GATT layers interfaces using the respective class) - * EnableBLE in turn registers the existance of a special App which wants to - * turn on Bluetooth Low enrgy part without making it visible at the settings UI - * as Bluetooth ON. - * <p>Invoking EnableBLE when Bluetooth is already in ON state, would just registers - * the existance of special Application and doesn't do anything to current BT state. - * when user turn OFF Bluetooth from UI, if there is an existance of special app, Bluetooth - * would stay in BLE_ON state so that LE features are still acessible to the special - * Applications. + * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE. * - * <p>This is an asynchronous call: it will return immediately, and + * enableBLE registers the existence of an app using only LE functions. + * + * enableBLE may enable Bluetooth to an LE only mode so that an app can use + * LE related features (BluetoothGatt or BluetoothGattServer classes) + * + * If the user disables Bluetooth while an app is registered to use LE only features, + * Bluetooth will remain on in LE only mode for the app. + * + * When Bluetooth is in LE only mode, it is not shown as ON to the UI. + * + * <p>This is an asynchronous call: it returns immediately, and * clients should listen for {@link #ACTION_BLE_STATE_CHANGED} - * to be notified of subsequent adapter state changes. If this call returns - * true, then the adapter state will immediately transition from {@link - * #STATE_OFF} to {@link #STATE_BLE_TURNING_ON}, and some time - * later transition to either {@link #STATE_OFF} or {@link - * #STATE_BLE_ON}. If this call returns false then there was an - * immediate problem that will prevent the adapter from being turned on - - * such as Airplane mode, or the adapter is already turned on. - * (@link #ACTION_BLE_STATE_CHANGED) returns the Bluetooth Adapter's various + * to be notified of adapter state changes. + * + * If this call returns * true, then the adapter state is either in a mode where + * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON}, + * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}. + * + * If this call returns false then there was an immediate problem that prevents the + * adapter from being turned on - such as Airplane mode. + * + * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various * states, It includes all the classic Bluetooth Adapter states along with * internal BLE only states * - * @return true to indicate Bluetooth LE start-up has begun, or false on + * @return true to indicate Bluetooth LE will be available, or false on * immediate error * @hide */ @@ -796,13 +762,14 @@ public final class BluetoothAdapter { if (!isBleScanAlwaysAvailable()) return false; try { - mManagerService.updateBleAppCount(mToken, true); + String packageName = ActivityThread.currentPackageName(); + mManagerService.updateBleAppCount(mToken, true, packageName); if (isLeEnabled()) { if (DBG) Log.d(TAG, "enableBLE(): Bluetooth already enabled"); return true; } if (DBG) Log.d(TAG, "enableBLE(): Calling enable"); - return mManagerService.enable(ActivityThread.currentPackageName()); + return mManagerService.enable(packageName); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1940,6 +1907,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.MAP_CLIENT) { BluetoothMapClient mapClient = new BluetoothMapClient(context, listener); return true; + } else if (profile == BluetoothProfile.INPUT_HOST) { + BluetoothInputHost iHost = new BluetoothInputHost(context, listener); + return true; } else { return false; } @@ -2016,6 +1986,10 @@ public final class BluetoothAdapter { BluetoothMapClient mapClient = (BluetoothMapClient)proxy; mapClient.close(); break; + case BluetoothProfile.INPUT_HOST: + BluetoothInputHost iHost = (BluetoothInputHost) proxy; + iHost.close(); + break; } } @@ -2087,7 +2061,7 @@ public final class BluetoothAdapter { return true; } try { - return mManagerService.enableNoAutoConnect(); + return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName()); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.aidl b/core/java/android/bluetooth/BluetoothCodecConfig.aidl new file mode 100644 index 000000000000..553e66e1dac5 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothCodecConfig.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +parcelable BluetoothCodecConfig; diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java new file mode 100644 index 000000000000..52cd2de4c2b6 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothCodecConfig.java @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Represents the codec configuration for a Bluetooth A2DP source device. + * + * {@see BluetoothA2dp} + * + * {@hide} + */ +public final class BluetoothCodecConfig implements Parcelable { + + /** + * Extra for the codec configuration intents of the individual profiles. + * + * This extra represents the current codec configuration of the A2DP + * profile. + */ + public static final String EXTRA_CODEC_CONFIG = "android.bluetooth.codec.extra.CODEC_CONFIG"; + + /** + * Extra for the codec configuration intents of the individual profiles. + * + * This extra represents the previous codec configuration of the A2DP + * profile. + */ + public static final String EXTRA_PREVIOUS_CODEC_CONFIG = + "android.bluetooth.codec.extra.PREVIOUS_CODEC_CONFIG"; + + // Add an entry for each source codec here. + // NOTE: The values should be same as those listed in the following file: + // hardware/libhardware/include/hardware/bt_av.h + public static final int SOURCE_CODEC_TYPE_SBC = 0; + public static final int SOURCE_CODEC_TYPE_APTX = 1; + public static final int SOURCE_CODEC_TYPE_APTX_HD = 2; + public static final int SOURCE_CODEC_TYPE_LDAC = 3; + + public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; + + public static final int CODEC_PRIORITY_DEFAULT = 0; + public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000; + + public static final int SAMPLE_RATE_NONE = 0; + public static final int SAMPLE_RATE_44100 = 0x1 << 0; + public static final int SAMPLE_RATE_48000 = 0x1 << 1; + public static final int SAMPLE_RATE_88200 = 0x1 << 2; + public static final int SAMPLE_RATE_96000 = 0x1 << 3; + public static final int SAMPLE_RATE_176400 = 0x1 << 4; + public static final int SAMPLE_RATE_192000 = 0x1 << 5; + + public static final int BITS_PER_SAMPLE_NONE = 0; + public static final int BITS_PER_SAMPLE_16 = 0x1 << 0; + public static final int BITS_PER_SAMPLE_24 = 0x1 << 1; + public static final int BITS_PER_SAMPLE_32 = 0x1 << 2; + + public static final int CHANNEL_MODE_NONE = 0; + public static final int CHANNEL_MODE_MONO = 0x1 << 0; + public static final int CHANNEL_MODE_STEREO = 0x1 << 1; + + private final int mCodecType; + private final int mCodecPriority; + private final int mSampleRate; + private final int mBitsPerSample; + private final int mChannelMode; + private final long mCodecSpecific1; + private final long mCodecSpecific2; + private final long mCodecSpecific3; + private final long mCodecSpecific4; + + public BluetoothCodecConfig(int codecType, int codecPriority, + int sampleRate, int bitsPerSample, + int channelMode,long codecSpecific1, + long codecSpecific2, long codecSpecific3, + long codecSpecific4) { + mCodecType = codecType; + mCodecPriority = codecPriority; + mSampleRate = sampleRate; + mBitsPerSample = bitsPerSample; + mChannelMode = channelMode; + mCodecSpecific1 = codecSpecific1; + mCodecSpecific2 = codecSpecific2; + mCodecSpecific3 = codecSpecific3; + mCodecSpecific4 = codecSpecific4; + } + + @Override + public boolean equals(Object o) { + if (o instanceof BluetoothCodecConfig) { + BluetoothCodecConfig other = (BluetoothCodecConfig)o; + return (other.mCodecType == mCodecType && + other.mCodecPriority == mCodecPriority && + other.mSampleRate == mSampleRate && + other.mBitsPerSample == mBitsPerSample && + other.mChannelMode == mChannelMode && + other.mCodecSpecific1 == mCodecSpecific1 && + other.mCodecSpecific2 == mCodecSpecific2 && + other.mCodecSpecific3 == mCodecSpecific3 && + other.mCodecSpecific4 == mCodecSpecific4); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(mCodecType, mCodecPriority, mSampleRate, + mBitsPerSample, mChannelMode, mCodecSpecific1, + mCodecSpecific2, mCodecSpecific3, mCodecSpecific4); + } + + @Override + public String toString() { + return "{mCodecType:" + mCodecType + + ",mCodecPriority:" + mCodecPriority + + ",mSampleRate:" + String.format("0x%x", mSampleRate) + + ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample) + + ",mChannelMode:" + String.format("0x%x", mChannelMode) + + ",mCodecSpecific1:" + mCodecSpecific1 + + ",mCodecSpecific2:" + mCodecSpecific2 + + ",mCodecSpecific3:" + mCodecSpecific3 + + ",mCodecSpecific4:" + mCodecSpecific4 + "}"; + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<BluetoothCodecConfig> CREATOR = + new Parcelable.Creator<BluetoothCodecConfig>() { + public BluetoothCodecConfig createFromParcel(Parcel in) { + final int codecType = in.readInt(); + final int codecPriority = in.readInt(); + final int sampleRate = in.readInt(); + final int bitsPerSample = in.readInt(); + final int channelMode = in.readInt(); + final long codecSpecific1 = in.readLong(); + final long codecSpecific2 = in.readLong(); + final long codecSpecific3 = in.readLong(); + final long codecSpecific4 = in.readLong(); + return new BluetoothCodecConfig(codecType, codecPriority, + sampleRate, bitsPerSample, + channelMode, codecSpecific1, + codecSpecific2, codecSpecific3, + codecSpecific4); + } + public BluetoothCodecConfig[] newArray(int size) { + return new BluetoothCodecConfig[size]; + } + }; + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mCodecType); + out.writeInt(mCodecPriority); + out.writeInt(mSampleRate); + out.writeInt(mBitsPerSample); + out.writeInt(mChannelMode); + out.writeLong(mCodecSpecific1); + out.writeLong(mCodecSpecific2); + out.writeLong(mCodecSpecific3); + out.writeLong(mCodecSpecific4); + } + + /** + * Returns the codec type. + * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}. + * + * @return the codec type + */ + public int getCodecType() { + return mCodecType; + } + + /** + * Returns the codec selection priority. + * The codec selection priority is relative to other codecs: larger value + * means higher priority. If 0, reset to default. + * + * @return the codec priority + */ + public int getCodecPriority() { + return mCodecPriority; + } + + /** + * Returns the codec sample rate. The value can be a bitmask with all + * supported sample rates: + * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or + * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or + * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_48000} or + * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_88200} or + * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_96000} or + * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_176400} or + * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_192000} + * + * @return the codec sample rate + */ + public int getSampleRate() { + return mSampleRate; + } + + /** + * Returns the codec bits per sample. The value can be a bitmask with all + * bits per sample supported: + * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or + * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or + * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_24} or + * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_32} + * + * @return the codec bits per sample + */ + public int getBitsPerSample() { + return mBitsPerSample; + } + + /** + * Returns the codec channel mode. The value can be a bitmask with all + * supported channel modes: + * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or + * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or + * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO} + * + * @return the codec channel mode + */ + public int getChannelMode() { + return mChannelMode; + } + + /** + * Returns a codec specific value1. + * + * @return a codec specific value1. + */ + public long getCodecSpecific1() { + return mCodecSpecific1; + } + + /** + * Returns a codec specific value2. + * + * @return a codec specific value2 + */ + public long getCodecSpecific2() { + return mCodecSpecific2; + } + + /** + * Returns a codec specific value3. + * + * @return a codec specific value3 + */ + public long getCodecSpecific3() { + return mCodecSpecific3; + } + + /** + * Returns a codec specific value4. + * + * @return a codec specific value4 + */ + public long getCodecSpecific4() { + return mCodecSpecific4; + } + + /** + * Checks whether the audio feeding parameters are same. + * + * @param other the codec config to compare against + * @return true if the audio feeding parameters are same, otherwise false + */ + public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) { + return (other != null && other.mSampleRate == mSampleRate && + other.mBitsPerSample == mBitsPerSample && + other.mChannelMode == mChannelMode); + } +} diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl new file mode 100644 index 000000000000..283a71790d3d --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.aidl @@ -0,0 +1,19 @@ +/* +** Copyright 2016, 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.bluetooth; + +parcelable BluetoothHidDeviceAppConfiguration; diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java new file mode 100644 index 000000000000..05ba64e981f1 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Random; + +/** @hide */ +public final class BluetoothHidDeviceAppConfiguration implements Parcelable { + private final long mHash; + + BluetoothHidDeviceAppConfiguration() { + Random rnd = new Random(); + mHash = rnd.nextLong(); + } + + BluetoothHidDeviceAppConfiguration(long hash) { + mHash = hash; + } + + @Override + public boolean equals(Object o) { + if (o instanceof BluetoothHidDeviceAppConfiguration) { + BluetoothHidDeviceAppConfiguration config = (BluetoothHidDeviceAppConfiguration) o; + return mHash == config.mHash; + } + return false; + } + + @Override + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<BluetoothHidDeviceAppConfiguration> CREATOR = + new Parcelable.Creator<BluetoothHidDeviceAppConfiguration>() { + + @Override + public BluetoothHidDeviceAppConfiguration createFromParcel(Parcel in) { + long hash = in.readLong(); + return new BluetoothHidDeviceAppConfiguration(hash); + } + + @Override + public BluetoothHidDeviceAppConfiguration[] newArray(int size) { + return new BluetoothHidDeviceAppConfiguration[size]; + } + }; + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeLong(mHash); + } +} diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl new file mode 100644 index 000000000000..14f91140af2b --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl @@ -0,0 +1,19 @@ +/* +** Copyright 2016, 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.bluetooth; + +parcelable BluetoothHidDeviceAppQosSettings; diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java new file mode 100644 index 000000000000..0d6530c11a91 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Random; + +/** @hide */ +public final class BluetoothHidDeviceAppQosSettings implements Parcelable { + + final public int serviceType; + final public int tokenRate; + final public int tokenBucketSize; + final public int peakBandwidth; + final public int latency; + final public int delayVariation; + + final static public int SERVICE_NO_TRAFFIC = 0x00; + final static public int SERVICE_BEST_EFFORT = 0x01; + final static public int SERVICE_GUARANTEED = 0x02; + + final static public int MAX = (int) 0xffffffff; + + public BluetoothHidDeviceAppQosSettings(int serviceType, int tokenRate, int tokenBucketSize, + int peakBandwidth, + int latency, int delayVariation) { + this.serviceType = serviceType; + this.tokenRate = tokenRate; + this.tokenBucketSize = tokenBucketSize; + this.peakBandwidth = peakBandwidth; + this.latency = latency; + this.delayVariation = delayVariation; + } + + @Override + public boolean equals(Object o) { + if (o instanceof BluetoothHidDeviceAppQosSettings) { + BluetoothHidDeviceAppQosSettings qos = (BluetoothHidDeviceAppQosSettings) o; + return false; + } + return false; + } + + @Override + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<BluetoothHidDeviceAppQosSettings> CREATOR = + new Parcelable.Creator<BluetoothHidDeviceAppQosSettings>() { + + @Override + public BluetoothHidDeviceAppQosSettings createFromParcel(Parcel in) { + + return new BluetoothHidDeviceAppQosSettings(in.readInt(), in.readInt(), in.readInt(), + in.readInt(), + in.readInt(), in.readInt()); + } + + @Override + public BluetoothHidDeviceAppQosSettings[] newArray(int size) { + return new BluetoothHidDeviceAppQosSettings[size]; + } + }; + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(serviceType); + out.writeInt(tokenRate); + out.writeInt(tokenBucketSize); + out.writeInt(peakBandwidth); + out.writeInt(latency); + out.writeInt(delayVariation); + } + + public int[] toArray() { + return new int[] { + serviceType, tokenRate, tokenBucketSize, peakBandwidth, latency, delayVariation + }; + } +} diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl new file mode 100644 index 000000000000..87dd10ee15f4 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl @@ -0,0 +1,19 @@ +/* +** Copyright 2016, 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.bluetooth; + +parcelable BluetoothHidDeviceAppSdpSettings; diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java new file mode 100644 index 000000000000..f9a224581953 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Random; + +/** @hide */ +public final class BluetoothHidDeviceAppSdpSettings implements Parcelable { + + final public String name; + final public String description; + final public String provider; + final public byte subclass; + final public byte[] descriptors; + + public BluetoothHidDeviceAppSdpSettings(String name, String description, String provider, + byte subclass, byte[] descriptors) { + this.name = name; + this.description = description; + this.provider = provider; + this.subclass = subclass; + this.descriptors = descriptors.clone(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof BluetoothHidDeviceAppSdpSettings) { + BluetoothHidDeviceAppSdpSettings sdp = (BluetoothHidDeviceAppSdpSettings) o; + return false; + } + return false; + } + + @Override + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<BluetoothHidDeviceAppSdpSettings> CREATOR = + new Parcelable.Creator<BluetoothHidDeviceAppSdpSettings>() { + + @Override + public BluetoothHidDeviceAppSdpSettings createFromParcel(Parcel in) { + + return new BluetoothHidDeviceAppSdpSettings(in.readString(), in.readString(), + in.readString(), in.readByte(), in.createByteArray()); + } + + @Override + public BluetoothHidDeviceAppSdpSettings[] newArray(int size) { + return new BluetoothHidDeviceAppSdpSettings[size]; + } + }; + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeString(name); + out.writeString(description); + out.writeString(provider); + out.writeByte(subclass); + out.writeByteArray(descriptors); + } +} diff --git a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java new file mode 100644 index 000000000000..f519776276fc --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import android.util.Log; + +/** @hide */ +public abstract class BluetoothHidDeviceCallback { + + private static final String TAG = BluetoothHidDeviceCallback.class.getSimpleName(); + + /** + * Callback called when application registration state changes. Usually it's + * called due to either + * {@link BluetoothHidDevice#registerApp(String, String, String, byte, byte[], + * BluetoothHidDeviceCallback)} + * or + * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)} + * , but can be also unsolicited in case e.g. Bluetooth was turned off in + * which case application is unregistered automatically. + * + * @param pluggedDevice {@link BluetoothDevice} object which represents host + * that currently has Virtual Cable established with device. Only + * valid when application is registered, can be <code>null</code> + * . + * @param config {@link BluetoothHidDeviceAppConfiguration} object which + * represents token required to unregister application using + * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)} + * . + * @param registered <code>true</code> if application is registered, + * <code>false</code> otherwise. + */ + public void onAppStatusChanged(BluetoothDevice pluggedDevice, + BluetoothHidDeviceAppConfiguration config, boolean registered) { + Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + pluggedDevice + " registered=" + + registered); + } + + /** + * Callback called when connection state with remote host was changed. + * Application can assume than Virtual Cable is established when called with + * {@link BluetoothProfile#STATE_CONNECTED} <code>state</code>. + * + * @param device {@link BluetoothDevice} object representing host device + * which connection state was changed. + * @param state Connection state as defined in {@link BluetoothProfile}. + */ + public void onConnectionStateChanged(BluetoothDevice device, int state) { + Log.d(TAG, "onConnectionStateChanged: device=" + device + " state=" + state); + } + + /** + * Callback called when GET_REPORT is received from remote host. Should be + * replied by application using + * {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte, byte[])}. + * + * @param type Requested Report Type. + * @param id Requested Report Id, can be 0 if no Report Id are defined in + * descriptor. + * @param bufferSize Requested buffer size, application shall respond with + * at least given number of bytes. + */ + public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) { + Log.d(TAG, "onGetReport: device=" + device + " type=" + type + " id=" + id + " bufferSize=" + + bufferSize); + } + + /** + * Callback called when SET_REPORT is received from remote host. In case + * received data are invalid, application shall respond with + * {@link BluetoothHidDevice#reportError(BluetoothDevice)}. + * + * @param type Report Type. + * @param id Report Id. + * @param data Report data. + */ + public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) { + Log.d(TAG, "onSetReport: device=" + device + " type=" + type + " id=" + id); + } + + /** + * Callback called when SET_PROTOCOL is received from remote host. + * Application shall use this information to send only reports valid for + * given protocol mode. By default, + * {@link BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed. + * + * @param protocol Protocol Mode. + */ + public void onSetProtocol(BluetoothDevice device, byte protocol) { + Log.d(TAG, "onSetProtocol: device=" + device + " protocol=" + protocol); + } + + /** + * Callback called when report data is received over interrupt channel. + * Report Type is assumed to be + * {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}. + * + * @param reportId Report Id. + * @param data Report data. + */ + public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) { + Log.d(TAG, "onIntrData: device=" + device + " reportId=" + reportId); + } + + /** + * Callback called when Virtual Cable is removed. This can be either due to + * {@link BluetoothHidDevice#unplug(BluetoothDevice)} or request from remote + * side. After this callback is received connection will be disconnected + * automatically. + */ + public void onVirtualCableUnplug(BluetoothDevice device) { + Log.d(TAG, "onVirtualCableUnplug: device=" + device); + } +} diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java new file mode 100644 index 000000000000..68d105f1155d --- /dev/null +++ b/core/java/android/bluetooth/BluetoothInputHost.java @@ -0,0 +1,558 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; + +/** + * @hide + */ +public final class BluetoothInputHost implements BluetoothProfile { + + private static final String TAG = BluetoothInputHost.class.getSimpleName(); + + /** + * Intent used to broadcast the change in connection state of the Input + * Host profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, + * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED"; + + /** + * Constants representing device subclass. + * + * @see #registerApp(String, String, String, byte, byte[], + * BluetoothHidDeviceCallback) + */ + public static final byte SUBCLASS1_NONE = (byte) 0x00; + public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40; + public static final byte SUBCLASS1_MOUSE = (byte) 0x80; + public static final byte SUBCLASS1_COMBO = (byte) 0xC0; + + public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00; + public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01; + public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02; + public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03; + public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04; + public static final byte SUBCLASS2_DIGITIZER_TABLED = (byte) 0x05; + public static final byte SUBCLASS2_CARD_READER = (byte) 0x06; + + /** + * Constants representing report types. + * + * @see BluetoothHidDeviceCallback#onGetReport(byte, byte, int) + * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[]) + * @see BluetoothHidDeviceCallback#onIntrData(byte, byte[]) + */ + public static final byte REPORT_TYPE_INPUT = (byte) 1; + public static final byte REPORT_TYPE_OUTPUT = (byte) 2; + public static final byte REPORT_TYPE_FEATURE = (byte) 3; + + /** + * Constants representing error response for Set Report. + * + * @see BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[]) + */ + public static final byte ERROR_RSP_SUCCESS = (byte) 0; + public static final byte ERROR_RSP_NOT_READY = (byte) 1; + public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2; + public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3; + public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4; + public static final byte ERROR_RSP_UNKNOWN = (byte) 14; + + /** + * Constants representing protocol mode used set by host. Default is always + * {@link #PROTOCOL_REPORT_MODE} unless notified otherwise. + * + * @see BluetoothHidDeviceCallback#onSetProtocol(byte) + */ + public static final byte PROTOCOL_BOOT_MODE = (byte) 0; + public static final byte PROTOCOL_REPORT_MODE = (byte) 1; + + private Context mContext; + + private ServiceListener mServiceListener; + + private IBluetoothInputHost mService; + + private BluetoothAdapter mAdapter; + + private static class BluetoothHidDeviceCallbackWrapper extends IBluetoothHidDeviceCallback.Stub { + + private BluetoothHidDeviceCallback mCallback; + + public BluetoothHidDeviceCallbackWrapper(BluetoothHidDeviceCallback callback) { + mCallback = callback; + } + + @Override + public void onAppStatusChanged(BluetoothDevice pluggedDevice, + BluetoothHidDeviceAppConfiguration config, boolean registered) { + mCallback.onAppStatusChanged(pluggedDevice, config, registered); + } + + @Override + public void onConnectionStateChanged(BluetoothDevice device, int state) { + mCallback.onConnectionStateChanged(device, state); + } + + @Override + public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) { + mCallback.onGetReport(device, type, id, bufferSize); + } + + @Override + public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) { + mCallback.onSetReport(device, type, id, data); + } + + @Override + public void onSetProtocol(BluetoothDevice device, byte protocol) { + mCallback.onSetProtocol(device, protocol); + } + + @Override + public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) { + mCallback.onIntrData(device, reportId, data); + } + + @Override + public void onVirtualCableUnplug(BluetoothDevice device) { + mCallback.onVirtualCableUnplug(device); + } + } + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + + public void onBluetoothStateChange(boolean up) { + Log.d(TAG, "onBluetoothStateChange: up=" + up); + synchronized (mConnection) { + if (!up) { + Log.d(TAG,"Unbinding service..."); + if (mService != null) { + mService = null; + try { + mContext.unbindService(mConnection); + } catch (IllegalArgumentException e) { + Log.e(TAG,"onBluetoothStateChange: could not unbind service:", e); + } + } + } else { + try { + if (mService == null) { + Log.d(TAG,"Binding HID Device service..."); + doBind(); + } + } catch (IllegalStateException e) { + Log.e(TAG,"onBluetoothStateChange: could not bind to HID Dev service: ", e); + } catch (SecurityException e) { + Log.e(TAG,"onBluetoothStateChange: could not bind to HID Dev service: ", e); + } + } + } + } + }; + + private ServiceConnection mConnection = new ServiceConnection() { + + public void onServiceConnected(ComponentName className, IBinder service) { + Log.d(TAG, "onServiceConnected()"); + + mService = IBluetoothInputHost.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST, + BluetoothInputHost.this); + } + } + + public void onServiceDisconnected(ComponentName className) { + Log.d(TAG, "onServiceDisconnected()"); + + mService = null; + + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_HOST); + } + } + }; + + BluetoothInputHost(Context context, ServiceListener listener) { + Log.v(TAG, "BluetoothInputHost"); + + mContext = context; + mServiceListener = listener; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothInputHost.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent); + return false; + } + Log.d(TAG, "Bound to HID Device Service"); + return true; + } + + void close() { + Log.v(TAG, "close()"); + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + synchronized (mConnection) { + if (mService != null) { + mService = null; + try { + mContext.unbindService(mConnection); + } catch (IllegalArgumentException e) { + Log.e(TAG,"close: could not unbind HID Dev service: ", e); + } + } + } + + mServiceListener = null; + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getConnectedDevices() { + Log.v(TAG, "getConnectedDevices()"); + + if (mService != null) { + try { + return mService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states)); + + if (mService != null) { + try { + return mService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public int getConnectionState(BluetoothDevice device) { + Log.v(TAG, "getConnectionState(): device=" + device); + + if (mService != null) { + try { + return mService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return STATE_DISCONNECTED; + } + + /** + * Registers application to be used for HID device. Connections to HID + * Device are only possible when application is registered. Only one + * application can be registered at time. When no longer used, application + * should be unregistered using + * {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}. + * + * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of + * HID Device SDP record. + * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of + * Incoming QoS Settings. + * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of + * Outgoing QoS Settings. + * @param callback {@link BluetoothHidDeviceCallback} object to which + * callback messages will be sent. + * @return + */ + public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp, + BluetoothHidDeviceAppQosSettings inQos, BluetoothHidDeviceAppQosSettings outQos, + BluetoothHidDeviceCallback callback) { + Log.v(TAG, "registerApp(): sdp=" + sdp + " inQos=" + inQos + " outQos=" + outQos + + " callback=" + callback); + + boolean result = false; + + if (sdp == null || callback == null) { + return false; + } + + if (mService != null) { + try { + BluetoothHidDeviceAppConfiguration config = + new BluetoothHidDeviceAppConfiguration(); + BluetoothHidDeviceCallbackWrapper cbw = + new BluetoothHidDeviceCallbackWrapper(callback); + result = mService.registerApp(config, sdp, inQos, outQos, cbw); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return result; + } + + /** + * Unregisters application. Active connection will be disconnected and no + * new connections will be allowed until registered again using + * {@link #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)} + * + * @param config {@link BluetoothHidDeviceAppConfiguration} object as + * obtained from + * {@link BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice, + * BluetoothHidDeviceAppConfiguration, boolean)} + * + * @return + */ + public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) { + Log.v(TAG, "unregisterApp()"); + + boolean result = false; + + if (mService != null) { + try { + result = mService.unregisterApp(config); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return result; + } + + /** + * Sends report to remote host using interrupt channel. + * + * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id + * are not defined in descriptor. + * @param data Report data, not including Report Id. + * @return + */ + public boolean sendReport(BluetoothDevice device, int id, byte[] data) { + boolean result = false; + + if (mService != null) { + try { + result = mService.sendReport(device, id, data); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return result; + } + + /** + * Sends report to remote host as reply for GET_REPORT request from + * {@link BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}. + * + * @param type Report Type, as in request. + * @param id Report Id, as in request. + * @param data Report data, not including Report Id. + * @return + */ + public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) { + Log.v(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id); + + boolean result = false; + + if (mService != null) { + try { + result = mService.replyReport(device, type, id, data); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return result; + } + + /** + * Sends error handshake message as reply for invalid SET_REPORT request + * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}. + * + * @param error Error to be sent for SET_REPORT via HANDSHAKE. + * @return + */ + public boolean reportError(BluetoothDevice device, byte error) { + Log.v(TAG, "reportError(): device=" + device + " error=" + error); + + boolean result = false; + + if (mService != null) { + try { + result = mService.reportError(device, error); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return result; + } + + /** + * Sends Virtual Cable Unplug to currently connected host. + * + * @return + */ + public boolean unplug(BluetoothDevice device) { + Log.v(TAG, "unplug(): device=" + device); + + boolean result = false; + + if (mService != null) { + try { + result = mService.unplug(device); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return result; + } + + /** + * Initiates connection to host which currently has Virtual Cable + * established with device. + * + * @return + */ + public boolean connect(BluetoothDevice device) { + Log.v(TAG, "connect(): device=" + device); + + boolean result = false; + + if (mService != null) { + try { + result = mService.connect(device); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return result; + } + + /** + * Disconnects from currently connected host. + * + * @return + */ + public boolean disconnect(BluetoothDevice device) { + Log.v(TAG, "disconnect(): device=" + device); + + boolean result = false; + + if (mService != null) { + try { + result = mService.disconnect(device); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + } + + return result; + } +} diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index f3636070fa5c..2f64c719ec10 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -143,11 +143,17 @@ public interface BluetoothProfile { public static final int MAP_CLIENT = 18; /** + * Input Host + * @hide + */ + static public final int INPUT_HOST = 19; + + /** * Max profile ID. This value should be updated whenever a new profile is added to match * the largest value assigned to a profile. * @hide */ - public static final int MAX_PROFILE_ID = 17; + public static final int MAX_PROFILE_ID = 19; /** * Default priority for devices that we try to auto-connect to and diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl index 26ff9e274c39..5b524eb18a5e 100644 --- a/core/java/android/bluetooth/IBluetoothA2dp.aidl +++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl @@ -16,6 +16,7 @@ package android.bluetooth; +import android.bluetooth.BluetoothCodecConfig; import android.bluetooth.BluetoothDevice; /** @@ -36,4 +37,6 @@ interface IBluetoothA2dp { oneway void adjustAvrcpAbsoluteVolume(int direction); oneway void setAvrcpAbsoluteVolume(int volume); boolean isA2dpPlaying(in BluetoothDevice device); + BluetoothCodecConfig getCodecConfig(); + oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig); } diff --git a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl new file mode 100644 index 000000000000..a737198ad954 --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016, 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.bluetooth; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHidDeviceAppConfiguration; + +/** @hide */ +interface IBluetoothHidDeviceCallback { + void onAppStatusChanged(in BluetoothDevice device, in BluetoothHidDeviceAppConfiguration config, boolean registered); + void onConnectionStateChanged(in BluetoothDevice device, in int state); + void onGetReport(in BluetoothDevice device, in byte type, in byte id, in int bufferSize); + void onSetReport(in BluetoothDevice device, in byte type, in byte id, in byte[] data); + void onSetProtocol(in BluetoothDevice device, in byte protocol); + void onIntrData(in BluetoothDevice device, in byte reportId, in byte[] data); + void onVirtualCableUnplug(in BluetoothDevice device); +} diff --git a/core/java/android/bluetooth/IBluetoothInputHost.aidl b/core/java/android/bluetooth/IBluetoothInputHost.aidl new file mode 100644 index 000000000000..6c4993f750e6 --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothInputHost.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHidDeviceAppConfiguration; +import android.bluetooth.IBluetoothHidDeviceCallback; +import android.bluetooth.BluetoothHidDeviceAppSdpSettings; +import android.bluetooth.BluetoothHidDeviceAppQosSettings; + +/** @hide */ +interface IBluetoothInputHost { + boolean registerApp(in BluetoothHidDeviceAppConfiguration config, + in BluetoothHidDeviceAppSdpSettings sdp, in BluetoothHidDeviceAppQosSettings inQos, + in BluetoothHidDeviceAppQosSettings outQos, in IBluetoothHidDeviceCallback callback); + boolean unregisterApp(in BluetoothHidDeviceAppConfiguration config); + boolean sendReport(in BluetoothDevice device, in int id, in byte[] data); + boolean replyReport(in BluetoothDevice device, in byte type, in byte id, in byte[] data); + boolean reportError(in BluetoothDevice device, byte error); + boolean unplug(in BluetoothDevice device); + boolean connect(in BluetoothDevice device); + boolean disconnect(in BluetoothDevice device); + List<BluetoothDevice> getConnectedDevices(); + List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states); + int getConnectionState(in BluetoothDevice device); +} diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl index 2ab9ae80b442..5afd77418222 100644 --- a/core/java/android/bluetooth/IBluetoothManager.aidl +++ b/core/java/android/bluetooth/IBluetoothManager.aidl @@ -35,8 +35,8 @@ interface IBluetoothManager void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback); boolean isEnabled(); boolean enable(String packageName); - boolean enableNoAutoConnect(); - boolean disable( String packageName, boolean persist); + boolean enableNoAutoConnect(String packageName); + boolean disable(String packageName, boolean persist); int getState(); IBluetoothGatt getBluetoothGatt(); @@ -47,6 +47,6 @@ interface IBluetoothManager String getName(); boolean isBleScanAlwaysAvailable(); - int updateBleAppCount(IBinder b, boolean enable); + int updateBleAppCount(IBinder b, boolean enable, String packageName); boolean isBleAppPresent(); } diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java index 9464222f091d..e1eaf00d0f20 100644 --- a/core/java/android/net/LocalServerSocket.java +++ b/core/java/android/net/LocalServerSocket.java @@ -87,9 +87,9 @@ public class LocalServerSocket { { LocalSocketImpl acceptedImpl = new LocalSocketImpl(); - impl.accept (acceptedImpl); + impl.accept(acceptedImpl); - return new LocalSocket(acceptedImpl, LocalSocket.SOCKET_UNKNOWN); + return LocalSocket.createLocalSocketForAccept(acceptedImpl, LocalSocket.SOCKET_UNKNOWN); } /** diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java index e14facb1abb5..d9ad74beb016 100644 --- a/core/java/android/net/LocalSocket.java +++ b/core/java/android/net/LocalSocket.java @@ -73,19 +73,27 @@ public class LocalSocket implements Closeable { this(new LocalSocketImpl(fd), SOCKET_UNKNOWN); isBound = true; isConnected = true; + implCreated = true; } - /** - * for use with AndroidServerSocket - * @param impl a SocketImpl - */ - /*package*/ LocalSocket(LocalSocketImpl impl, int sockType) { + private LocalSocket(LocalSocketImpl impl, int sockType) { this.impl = impl; this.sockType = sockType; this.isConnected = false; this.isBound = false; } + /** + * for use with LocalServerSocket.accept() + */ + static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl, int sockType) { + LocalSocket socket = new LocalSocket(impl, sockType); + socket.isConnected = true; + socket.isBound = true; + socket.implCreated = true; + return socket; + } + /** {@inheritDoc} */ @Override public String toString() { @@ -216,11 +224,11 @@ public class LocalSocket implements Closeable { implCreateIfNeeded(); impl.shutdownOutput(); } - + public void setReceiveBufferSize(int size) throws IOException { impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); } - + public int getReceiveBufferSize() throws IOException { return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue(); } @@ -228,7 +236,7 @@ public class LocalSocket implements Closeable { public void setSoTimeout(int n) throws IOException { impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n)); } - + public int getSoTimeout() throws IOException { return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue(); } @@ -236,7 +244,7 @@ public class LocalSocket implements Closeable { public void setSendBufferSize(int n) throws IOException { impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n)); } - + public int getSendBufferSize() throws IOException { return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue(); } @@ -321,5 +329,5 @@ public class LocalSocket implements Closeable { */ public FileDescriptor getFileDescriptor() { return impl.getFileDescriptor(); - } + } } diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java index 0f0e9c49a0b0..d8f782115cf8 100644 --- a/core/java/android/net/LocalSocketImpl.java +++ b/core/java/android/net/LocalSocketImpl.java @@ -235,29 +235,29 @@ class LocalSocketImpl * @throws IOException */ public void create(int sockType) throws IOException { - // no error if socket already created - // need this for LocalServerSocket.accept() - if (fd == null) { - int osType; - switch (sockType) { - case LocalSocket.SOCKET_DGRAM: - osType = OsConstants.SOCK_DGRAM; - break; - case LocalSocket.SOCKET_STREAM: - osType = OsConstants.SOCK_STREAM; - break; - case LocalSocket.SOCKET_SEQPACKET: - osType = OsConstants.SOCK_SEQPACKET; - break; - default: - throw new IllegalStateException("unknown sockType"); - } - try { - fd = Os.socket(OsConstants.AF_UNIX, osType, 0); - mFdCreatedInternally = true; - } catch (ErrnoException e) { - e.rethrowAsIOException(); - } + if (fd != null) { + throw new IOException("LocalSocketImpl already has an fd"); + } + + int osType; + switch (sockType) { + case LocalSocket.SOCKET_DGRAM: + osType = OsConstants.SOCK_DGRAM; + break; + case LocalSocket.SOCKET_STREAM: + osType = OsConstants.SOCK_STREAM; + break; + case LocalSocket.SOCKET_SEQPACKET: + osType = OsConstants.SOCK_SEQPACKET; + break; + default: + throw new IllegalStateException("unknown sockType"); + } + try { + fd = Os.socket(OsConstants.AF_UNIX, osType, 0); + mFdCreatedInternally = true; + } catch (ErrnoException e) { + e.rethrowAsIOException(); } } diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java index 4282ca75f2b6..ec0bb25d28eb 100644 --- a/core/java/android/net/NetworkScorerAppManager.java +++ b/core/java/android/net/NetworkScorerAppManager.java @@ -231,13 +231,7 @@ public class NetworkScorerAppManager { if (defaultApp == null) { return false; } - if (callingUid != defaultApp.packageUid) { - return false; - } - // To be extra safe, ensure the caller holds the SCORE_NETWORKS permission. It always - // should, since it couldn't become the active scorer otherwise, but this can't hurt. - return mContext.checkCallingPermission(Manifest.permission.SCORE_NETWORKS) == - PackageManager.PERMISSION_GRANTED; + return callingUid == defaultApp.packageUid; } private boolean isNetworkRecommendationsDisabled() { diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java index a96f90d57746..d013f6442f23 100644 --- a/core/java/android/net/RecommendationRequest.java +++ b/core/java/android/net/RecommendationRequest.java @@ -41,6 +41,7 @@ public final class RecommendationRequest implements Parcelable { * Builder class for constructing {@link RecommendationRequest} instances. * @hide */ + @SystemApi public static final class Builder { private ScanResult[] mScanResults; private WifiConfiguration mCurrentConfig; diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 151239bed02b..f6edee0f78e7 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -783,7 +783,7 @@ public class Build { */ public static boolean isBuildConsistent() { // Don't care on eng builds. Incremental build may trigger false negative. - if ("eng".equals(TYPE)) return true; + if (IS_ENG) return true; final String system = SystemProperties.get("ro.build.fingerprint"); final String vendor = SystemProperties.get("ro.vendor.build.fingerprint"); @@ -847,6 +847,10 @@ public class Build { public static final boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1; + /** {@hide} */ + public static final boolean IS_ENG = + "eng".equals(getString("ro.build.type")); + /** * Specifies whether the permissions needed by a legacy app should be * reviewed before any of its components can run. A legacy app is one diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java index 481b2dc096d5..e02549426cb5 100644 --- a/core/java/android/os/HwBinder.java +++ b/core/java/android/os/HwBinder.java @@ -17,6 +17,7 @@ package android.os; import java.util.ArrayList; +import java.util.NoSuchElementException; import libcore.util.NativeAllocationRegistry; /** @hide */ @@ -33,19 +34,24 @@ public abstract class HwBinder implements IHwBinder { mNativeContext); } + @Override public final native void transact( - int code, HwParcel request, HwParcel reply, int flags); + int code, HwParcel request, HwParcel reply, int flags) + throws RemoteException; public abstract void onTransact( - int code, HwParcel request, HwParcel reply, int flags); + int code, HwParcel request, HwParcel reply, int flags) + throws RemoteException; public native final void registerService( ArrayList<String> interfaceChain, - String serviceName); + String serviceName) + throws RemoteException; public static native final IHwBinder getService( String iface, - String serviceName); + String serviceName) + throws RemoteException, NoSuchElementException; // Returns address of the "freeFunction". private static native final long native_init(); diff --git a/core/java/android/os/HwRemoteBinder.java b/core/java/android/os/HwRemoteBinder.java index e617e0a52bc6..2f89ce6270be 100644 --- a/core/java/android/os/HwRemoteBinder.java +++ b/core/java/android/os/HwRemoteBinder.java @@ -32,12 +32,15 @@ public class HwRemoteBinder implements IHwBinder { mNativeContext); } + @Override public IHwInterface queryLocalInterface(String descriptor) { return null; } + @Override public native final void transact( - int code, HwParcel request, HwParcel reply, int flags); + int code, HwParcel request, HwParcel reply, int flags) + throws RemoteException; public native boolean linkToDeath(DeathRecipient recipient, long cookie); public native boolean unlinkToDeath(DeathRecipient recipient); diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java index f93bfd79f625..619f4dc631d5 100644 --- a/core/java/android/os/IHwBinder.java +++ b/core/java/android/os/IHwBinder.java @@ -23,7 +23,8 @@ public interface IHwBinder { public static final int FLAG_ONEWAY = 1; public void transact( - int code, HwParcel request, HwParcel reply, int flags); + int code, HwParcel request, HwParcel reply, int flags) + throws RemoteException; public IHwInterface queryLocalInterface(String descriptor); @@ -36,6 +37,5 @@ public interface IHwBinder { } public boolean linkToDeath(DeathRecipient recipient, long cookie); - public boolean unlinkToDeath(DeathRecipient recipient); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 9cd1a4246a58..d6688e3c00f7 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -184,6 +184,11 @@ public class Process { */ public static final int LAST_SHARED_APPLICATION_GID = 59999; + /** {@hide} */ + public static final int FIRST_APPLICATION_CACHE_GID = 20000; + /** {@hide} */ + public static final int LAST_APPLICATION_CACHE_GID = 29999; + /** * Standard priority of application threads. * Use with {@link #setThreadPriority(int)} and diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index b3f44536214b..535a05a9fcb1 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -213,6 +213,15 @@ public final class UserHandle implements Parcelable { } /** + * Returns the cache GID for a given UID or appId. + * @hide + */ + public static int getCacheAppGid(int id) { + return Process.FIRST_APPLICATION_CACHE_GID + (id % PER_USER_RANGE) + - Process.FIRST_APPLICATION_UID; + } + + /** * Generate a text representation of the uid, breaking out its individual * components -- user, app, isolated, etc. * @hide diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index c5507b9841bc..2bc05655b55c 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -40,6 +40,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -930,22 +931,29 @@ public class StorageManager { } /** {@hide} */ - public long getPrimaryStorageSize() { + public static Pair<String, Long> getPrimaryStoragePathAndSize() { for (String path : INTERNAL_STORAGE_SIZE_PATHS) { final long numberBlocks = readLong(path); if (numberBlocks > 0) { - return numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE; + return new Pair<>(path, Long.valueOf(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE)); } } - return 0; + return null; + } + + + /** {@hide} */ + public long getPrimaryStorageSize() { + final Pair<String, Long> pair = getPrimaryStoragePathAndSize(); + return pair == null ? 0 : pair.second.longValue(); } - private long readLong(String path) { + private static long readLong(String path) { try (final FileInputStream fis = new FileInputStream(path); final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) { return Long.parseLong(reader.readLine()); } catch (Exception e) { - Slog.w(TAG, "Could not read " + path, e); + Slog.w(TAG, "readLong(): could not read " + path + ": " + e); return 0; } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e52983e995df..3ea5dcba815d 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6498,7 +6498,8 @@ public final class Settings { QS_TILES, DOZE_ENABLED, DOZE_PULSE_ON_PICK_UP, - DOZE_PULSE_ON_DOUBLE_TAP + DOZE_PULSE_ON_DOUBLE_TAP, + NFC_PAYMENT_DEFAULT_COMPONENT }; /** diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index e0d589a8a8fb..2d6f44352ba7 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -24,6 +24,8 @@ import android.os.ZygoteProcess; import android.text.TextUtils; import android.util.Log; +import com.android.internal.annotations.GuardedBy; + import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -38,70 +40,104 @@ public class WebViewZygote { private static final String WEBVIEW_ZYGOTE_SERVICE_32 = "webview_zygote32"; private static final String WEBVIEW_ZYGOTE_SERVICE_64 = "webview_zygote64"; + /** + * Lock object that protects all other static members. + */ + private static final Object sLock = new Object(); + + /** + * Instance that maintains the socket connection to the zygote. This is null if the zygote + * is not running or is not connected. + */ + @GuardedBy("sLock") private static ZygoteProcess sZygote; + /** + * Information about the selected WebView package. This is set from #onWebViewProviderChanged(). + */ + @GuardedBy("sLock") private static PackageInfo sPackage; + /** + * Flag for whether multi-process WebView is enabled. If this is false, the zygote + * will not be started. + */ + @GuardedBy("sLock") private static boolean sMultiprocessEnabled = false; public static ZygoteProcess getProcess() { - connectToZygoteIfNeeded(); - return sZygote; + synchronized (sLock) { + connectToZygoteIfNeededLocked(); + return sZygote; + } } public static String getPackageName() { - return sPackage.packageName; + synchronized (sLock) { + return sPackage.packageName; + } } public static boolean isMultiprocessEnabled() { - return sMultiprocessEnabled && sPackage != null; + synchronized (sLock) { + return sMultiprocessEnabled && sPackage != null; + } } public static void setMultiprocessEnabled(boolean enabled) { - sMultiprocessEnabled = enabled; - - // When toggling between multi-process being on/off, start or stop the - // service. If it is enabled and the zygote is not yet started, bring up the service. - // Otherwise, bring down the service. The name may be null if the package - // information has not yet been resolved. - final String serviceName = getServiceName(); - if (serviceName == null) return; - - if (enabled && sZygote == null) { - SystemService.start(serviceName); - } else { - SystemService.stop(serviceName); - sZygote = null; + synchronized (sLock) { + sMultiprocessEnabled = enabled; + + // When toggling between multi-process being on/off, start or stop the + // service. If it is enabled and the zygote is not yet started, bring up the service. + // Otherwise, bring down the service. The name may be null if the package + // information has not yet been resolved. + final String serviceName = getServiceNameLocked(); + if (serviceName == null) return; + + if (enabled && sZygote == null) { + SystemService.start(serviceName); + } else { + SystemService.stop(serviceName); + sZygote = null; + } } } public static void onWebViewProviderChanged(PackageInfo packageInfo) { - sPackage = packageInfo; - - // If multi-process is not enabled, then do not start the zygote service. - if (!sMultiprocessEnabled) { - return; - } + String serviceName; + synchronized (sLock) { + sPackage = packageInfo; - final String serviceName = getServiceName(); + // If multi-process is not enabled, then do not start the zygote service. + if (!sMultiprocessEnabled) { + return; + } - if (SystemService.isStopped(serviceName)) { - SystemService.start(serviceName); - } else if (sZygote != null) { - SystemService.restart(serviceName); - } + serviceName = getServiceNameLocked(); + sZygote = null; - try { - SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000); - } catch (TimeoutException e) { - Log.e(LOGTAG, "Timed out waiting for " + serviceName); - return; + // The service may enter the RUNNING state before it opens the socket, + // so connectToZygoteIfNeededLocked() may still fail. + if (SystemService.isStopped(serviceName)) { + SystemService.start(serviceName); + } else { + SystemService.restart(serviceName); + } + + try { + SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000); + } catch (TimeoutException e) { + Log.e(LOGTAG, "Timed out waiting for " + serviceName); + return; + } + + connectToZygoteIfNeededLocked(); } - - connectToZygoteIfNeeded(); } - private static String getServiceName() { + @GuardedBy("sLock") + private static String getServiceNameLocked() { if (sPackage == null) return null; @@ -113,7 +149,8 @@ public class WebViewZygote { return WEBVIEW_ZYGOTE_SERVICE_32; } - private static void connectToZygoteIfNeeded() { + @GuardedBy("sLock") + private static void connectToZygoteIfNeededLocked() { if (sZygote != null) return; @@ -122,7 +159,7 @@ public class WebViewZygote { return; } - final String serviceName = getServiceName(); + final String serviceName = getServiceNameLocked(); if (!SystemService.isRunning(serviceName)) { Log.e(LOGTAG, serviceName + " is not running"); return; diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp index 8eb39e1aac58..fbccfd5532e2 100644 --- a/core/jni/android_hardware_location_ContextHubService.cpp +++ b/core/jni/android_hardware_location_ContextHubService.cpp @@ -33,6 +33,7 @@ #include <unordered_map> #include <queue> +#include <android-base/macros.h> #include <cutils/log.h> #include "JNIHelp.h" @@ -704,10 +705,10 @@ static void passOnOsResponse(uint32_t hubHandle, uint32_t msgType, } jbyteArray jmsg = env->NewByteArray(msgLen); - jintArray jheader = env->NewIntArray(sizeof(header)); + jintArray jheader = env->NewIntArray(arraysize(header)); env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg); - env->SetIntArrayRegion(jheader, 0, sizeof(header), (jint *)header); + env->SetIntArrayRegion(jheader, 0, arraysize(header), (jint *)header); ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32, header[HEADER_FIELD_MSG_TYPE], header[HEADER_FIELD_APP_INSTANCE], diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 497600212095..d30e6eba48e7 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -457,6 +457,18 @@ android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, ji } static jint +android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name) +{ + const char *c_address = env->GetStringUTFChars(device_address, NULL); + const char *c_name = env->GetStringUTFChars(device_name, NULL); + int status = check_AudioSystem_Command(AudioSystem::handleDeviceConfigChange(static_cast <audio_devices_t>(device), + c_address, c_name)); + env->ReleaseStringUTFChars(device_address, c_address); + env->ReleaseStringUTFChars(device_name, c_name); + return (jint) status; +} + +static jint android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state) { return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state)); @@ -1757,6 +1769,7 @@ static const JNINativeMethod gMethods[] = { {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId}, {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState}, {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState}, + {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_handleDeviceConfigChange}, {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState}, {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse}, {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse}, diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp index d6d431019a6d..37b6df1e3d2c 100644 --- a/core/jni/android_net_LocalSocketImpl.cpp +++ b/core/jni/android_net_LocalSocketImpl.cpp @@ -202,9 +202,7 @@ static ssize_t socket_read_all(JNIEnv *env, jobject thisJ, int fd, msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); - do { - ret = recvmsg(fd, &msg, MSG_NOSIGNAL); - } while (ret < 0 && errno == EINTR); + ret = TEMP_FAILURE_RETRY(recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC)); if (ret < 0 && errno == EPIPE) { // Treat this as an end of stream diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp index 95e031bd96d8..20bb885eb578 100644 --- a/core/jni/android_os_HwBinder.cpp +++ b/core/jni/android_os_HwBinder.cpp @@ -39,6 +39,8 @@ using android::AndroidRuntime; using android::hardware::hidl_vec; using android::hardware::hidl_string; +template<typename T> +using Return = android::hardware::Return<T>; #define PACKAGE_PATH "android/os" #define CLASS_NAME "HwBinder" @@ -52,6 +54,8 @@ static struct { jmethodID get; } gArrayListMethods; +static jclass gErrorClass; + static struct fields_t { jfieldID contextID; jmethodID onTransactID; @@ -144,6 +148,22 @@ status_t JHwBinder::onTransact( replyObj.get(), flags); + if (env->ExceptionCheck()) { + jthrowable excep = env->ExceptionOccurred(); + env->ExceptionDescribe(); + + if (env->IsInstanceOf(excep, gErrorClass)) { + /* It's an error */ + LOG(ERROR) << "Forcefully exiting"; + exit(1); + } else { + env->ExceptionClear(); + LOG(ERROR) << "Uncaught exception!"; + } + + env->DeleteLocalRef(excep); + } + status_t err = OK; if (!replyContext->wasSent()) { @@ -239,8 +259,6 @@ static void JHwBinder_native_registerService( hidl_vec<hidl_string> interfaceChain; interfaceChain.setToExternal(strings, numInterfaces, true /* shouldOwn */); - using android::hidl::manager::V1_0::IServiceManager; - sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz); /* TODO(b/33440494) this is not right */ @@ -250,24 +268,23 @@ static void JHwBinder_native_registerService( if (manager == nullptr) { LOG(ERROR) << "Could not get hwservicemanager."; - signalExceptionForError(env, UNKNOWN_ERROR); + signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */); return; } - bool ok = manager->add( - interfaceChain, - serviceName, - base); + Return<bool> ret = manager->add(interfaceChain, serviceName, base); env->ReleaseStringUTFChars(serviceNameObj, serviceName); serviceName = NULL; + bool ok = ret.isOk() && ret; + if (ok) { LOG(INFO) << "Starting thread pool."; ::android::hardware::ProcessState::self()->startThreadPool(); } - signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR)); + signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR), true /* canThrowRemoteException */); } static jobject JHwBinder_native_getService( @@ -303,19 +320,18 @@ static jobject JHwBinder_native_getService( if (manager == nullptr) { LOG(ERROR) << "Could not get hwservicemanager."; - signalExceptionForError(env, UNKNOWN_ERROR); + signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */); return NULL; } - sp<hardware::IBinder> service; - manager->get( - ifaceName, - serviceName, - [&service](sp<hidl::base::V1_0::IBase> out) { - service = hardware::toBinder< - hidl::base::V1_0::IBase, hidl::base::V1_0::BpBase - >(out); - }); + Return<sp<hidl::base::V1_0::IBase>> ret = manager->get(ifaceName, serviceName); + + if (!ret.isOk()) { + signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */); + } + + sp<hardware::IBinder> service = hardware::toBinder< + hidl::base::V1_0::IBase, hidl::base::V1_0::BpBase>(ret); env->ReleaseStringUTFChars(ifaceNameObj, ifaceName); ifaceName = NULL; @@ -356,6 +372,9 @@ int register_android_os_HwBinder(JNIEnv *env) { gArrayListMethods.size = GetMethodIDOrDie(env, arrayListClass, "size", "()I"); gArrayListMethods.get = GetMethodIDOrDie(env, arrayListClass, "get", "(I)Ljava/lang/Object;"); + jclass errorClass = FindClassOrDie(env, "java/lang/Error"); + gErrorClass = MakeGlobalRefOrDie(env, errorClass); + return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp index a10d80746e46..b9d810a4190b 100644 --- a/core/jni/android_os_HwParcel.cpp +++ b/core/jni/android_os_HwParcel.cpp @@ -49,7 +49,7 @@ static struct fields_t { } gFields; -void signalExceptionForError(JNIEnv *env, status_t err) { +void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException) { switch (err) { case OK: break; @@ -114,8 +114,13 @@ void signalExceptionForError(JNIEnv *env, status_t err) { default: { + std::stringstream ss; + ss << "HwBinder Error: (" << err << ")"; + jniThrowException( - env, "java/lang/RuntimeException", "Unknown error"); + env, + canThrowRemoteException ? "android/os/RemoteException" : "java/lang/RuntimeException", + ss.str().c_str()); break; } diff --git a/core/jni/android_os_HwParcel.h b/core/jni/android_os_HwParcel.h index 708bbba1901c..f81de9bf30b7 100644 --- a/core/jni/android_os_HwParcel.h +++ b/core/jni/android_os_HwParcel.h @@ -67,7 +67,7 @@ private: DISALLOW_COPY_AND_ASSIGN(JHwParcel); }; -void signalExceptionForError(JNIEnv *env, status_t err); +void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException = false); int register_android_os_HwParcel(JNIEnv *env); } // namespace android diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp index 0a7d84d9c8c5..f2f8e52db9f5 100644 --- a/core/jni/android_os_HwRemoteBinder.cpp +++ b/core/jni/android_os_HwRemoteBinder.cpp @@ -347,7 +347,7 @@ static void JHwRemoteBinder_native_transact( JHwParcel::GetNativeContext(env, replyObj)->getParcel(); status_t err = binder->transact(code, *request, reply, flags); - signalExceptionForError(env, err); + signalExceptionForError(env, err, true /* canThrowRemoteException */); } static jboolean JHwRemoteBinder_linkToDeath(JNIEnv* env, jobject thiz, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4e98e34d9ebd..7cf11d4ec5b2 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -167,6 +167,8 @@ <protected-broadcast android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" /> <protected-broadcast + android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" /> @@ -181,6 +183,8 @@ <protected-broadcast android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" /> <protected-broadcast + android:name="android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED" /> @@ -1228,6 +1232,12 @@ <permission android:name="android.permission.SCORE_NETWORKS" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi Allows applications to request network + recommendations and scores from the NetworkScoreService. + <p>Not for use by third-party applications. @hide --> + <permission android:name="android.permission.REQUEST_NETWORK_SCORES" + android:protectionLevel="signature|privileged" /> + <!-- ======================================= --> <!-- Permissions for short range, peripheral networks --> <!-- ======================================= --> @@ -2044,6 +2054,12 @@ <permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING" android:protectionLevel="signature" /> + <!-- Allows the system to bind to the discovered Network Recommendation Service. + @SystemApi @hide --> + <permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE" + android:protectionLevel="signature" /> + <uses-permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"/> + <!-- ========================================= --> <!-- Permissions for special development tools --> <!-- ========================================= --> @@ -2632,7 +2648,10 @@ android:protectionLevel="signature" /> <!-- @SystemApi Allows an application to broadcast privileged networking requests. - <p>Not for use by third-party applications. @hide --> + <p>Not for use by third-party applications. + @hide + @deprecated Use {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} instead + --> <permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED" android:protectionLevel="signature|privileged" /> diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java index 5bfff26b0813..29020bad5149 100644 --- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java +++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java @@ -169,6 +169,25 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase { assertNull(activeScorer); } + public void testIsCallerActiveScorer_providerNotAvailable() throws Exception { + ContentResolver cr = mTargetContext.getContentResolver(); + Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1); + + assertFalse(mNetworkScorerAppManager.isCallerActiveScorer(924)); + } + + public void testIsCallerActiveScorer_providerAvailable() throws Exception { + setNetworkRecommendationPackageNames("package1"); + mockScoreNetworksGranted("package1"); + mockRecommendationServiceAvailable("package1", 924 /* packageUid */); + + ContentResolver cr = mTargetContext.getContentResolver(); + Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1); + + assertTrue(mNetworkScorerAppManager.isCallerActiveScorer(924)); + assertFalse(mNetworkScorerAppManager.isCallerActiveScorer(925)); + } + private void setNetworkRecommendationPackageNames(String... names) { if (names == null) { names = new String[0]; diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk index 9b2b9f18a883..836ede61bba6 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk @@ -23,7 +23,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_SDK_VERSION := current +LOCAL_SDK_VERSION := 8 LOCAL_PACKAGE_NAME := MultiDexLegacyAndException diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk index 874263f5b82d..2915914033f7 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk @@ -23,7 +23,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_SDK_VERSION := current +LOCAL_SDK_VERSION := 8 LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp @@ -45,7 +45,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_SDK_VERSION := current +LOCAL_SDK_VERSION := 8 LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp2 diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd index 5d6b3a8f2e3f..1f1939c8e82d 100755 --- a/docs/html/google/play/billing/billing_integrate.jd +++ b/docs/html/google/play/billing/billing_integrate.jd @@ -294,7 +294,7 @@ ArrayList<String> skuList = new ArrayList<String> (); skuList.add("premiumUpgrade"); skuList.add("gas"); Bundle querySkus = new Bundle(); -querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList); +querySkus.putStringArrayList("ITEM_ID_LIST", skuList); </pre> <p> diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 33c1c3f6acc0..ce75bb4957f5 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -3278,6 +3278,20 @@ public class AudioManager { return delay; } + /** + * Indicate A2DP device configuration has changed. + * @param device Bluetooth device whose configuration has changed. + * {@hide} + */ + public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device) { + IAudioService service = getService(); + try { + service.handleBluetoothA2dpDeviceConfigChange(device); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** {@hide} */ public IRingtonePlayer getRingtonePlayer() { try { diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index f597440ccbb3..8a2825500670 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -678,6 +678,9 @@ public class AudioSystem public static native int setDeviceConnectionState(int device, int state, String device_address, String device_name); public static native int getDeviceConnectionState(int device, String device_address); + public static native int handleDeviceConfigChange(int device, + String device_address, + String device_name); public static native int setPhoneState(int state); public static native int setForceUse(int usage, int config); public static native int getForceUse(int usage); diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index c7931fcd297b..9e5ac7231925 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -133,6 +133,8 @@ interface IAudioService { int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state, int profile); + void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device); + AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer); boolean isCameraSoundForced(); diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 949acc0e1758..d0f8b73bbbeb 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -2336,10 +2336,7 @@ public class MediaPlayer extends PlayerBase } private void scanInternalSubtitleTracks() { - if (mSubtitleController == null) { - Log.d(TAG, "setSubtitleAnchor in MediaPlayer"); - setSubtitleAnchor(); - } + setSubtitleAnchor(); populateInbandTracks(); diff --git a/native/android/Android.bp b/native/android/Android.bp index 33c9655d647e..58436371ae27 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -17,4 +17,5 @@ ndk_library { name: "libandroid.ndk", symbol_file: "libandroid.map.txt", first_version: "9", + unversioned_until: "current", } diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp index e09b0b4443cd..17feb53bdb68 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -17,4 +17,5 @@ ndk_library { name: "libjnigraphics.ndk", symbol_file: "libjnigraphics.map.txt", first_version: "9", + unversioned_until: "current", } diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index 5b11303247ef..f79cf04835a2 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -100,6 +100,129 @@ <item>Always use HDCP checking</item> </string-array> + + <!-- Bluetooth settings --> + + <!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_titles"> + <item>Default</item> + <item>SBC</item> + <item>aptX</item> + <item>aptX-HD</item> + <item>LDAC</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec selection preference. --> + <string-array name="bluetooth_a2dp_codec_values" translatable="false" > + <item>1000000</item> + <item>0</item> + <item>1</item> + <item>2</item> + <item>3</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_summaries" > + <item>Default</item> + <item>SBC</item> + <item>aptX</item> + <item>aptX-HD</item> + <item>LDAC</item> + </string-array> + + <!-- Titles for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> + <item>Default</item> + <item>44.1 kHz</item> + <item>48.0 kHz</item> + <item>88.2 kHz</item> + <item>96.0 kHz</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec Sample Rate selection preference. --> + <string-array name="bluetooth_a2dp_codec_sample_rate_values" translatable="false" > + <item>0</item> + <item>1</item> + <item>2</item> + <item>4</item> + <item>8</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_sample_rate_summaries" > + <item>Default</item> + <item>44.1 kHz</item> + <item>48.0 kHz</item> + <item>88.2 kHz</item> + <item>96.0 kHz</item> + </string-array> + + <!-- Titles for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles"> + <item>Default</item> + <item>16 bits/sample</item> + <item>24 bits/sample</item> + <item>32 bits/sample</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec Bits Per Sample selection preference. --> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_values" translatable="false" > + <item>0</item> + <item>1</item> + <item>2</item> + <item>4</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries" > + <item>Default</item> + <item>16 bits/sample</item> + <item>24 bits/sample</item> + <item>32 bits/sample</item> + </string-array> + + <!-- Titles for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_channel_mode_titles"> + <item>Default</item> + <item>Mono</item> + <item>Stereo</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec Channel Mode selection preference. --> + <string-array name="bluetooth_a2dp_codec_channel_mode_values" translatable="false" > + <item>0</item> + <item>1</item> + <item>2</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_channel_mode_summaries" > + <item>Default</item> + <item>Mono</item> + <item>Stereo</item> + </string-array> + + <!-- Titles for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=40] --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item>Sound quality preferred (990kbps/909kbps)</item> + <item>Standard (660kbps/606kbps)</item> + <item>Connection preferred (330kbps/303kbps)</item> + </string-array> + + <!-- Values for Bluetooth Audio Codec LDAC Playback Quaility selection preference. --> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_values" translatable="false" > + <item>1000</item> + <item>1001</item> + <item>1002</item> + </string-array> + + <!-- Summaries for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=40]--> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries" > + <item>Sound quality preferred (990kbps/909kbps)</item> + <item>Standard (660kbps/606kbps)</item> + <item>Connection preferred (330kbps/303kbps)</item> + </string-array> + <!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] --> <string-array name="select_logd_size_titles"> <item>Off</item> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 29839e7cbff9..f389000dc01b 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -428,6 +428,31 @@ <!-- Setting Checkbox title for disabling Bluetooth absolute volume --> <string name="bluetooth_disable_absolute_volume">Disable absolute volume</string> + <!-- UI debug setting: Select Bluetooth Audio Codec --> + <string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec --> + <string name="bluetooth_select_a2dp_codec_type_dialog_title">Select Preferred Bluetooth A2DP Codec</string> + + <!-- UI debug setting: Select Bluetooth Audio Sample Rate --> + <string name="bluetooth_select_a2dp_codec_sample_rate">Bluetooth Audio Sample Rate</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Sample Rate --> + <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title">Select Preferred Bluetooth A2DP Codec Sample Rate</string> + + <!-- UI debug setting: Select Bluetooth Audio Bits Per Sample --> + <string name="bluetooth_select_a2dp_codec_bits_per_sample">Bluetooth Audio Bits Per Sample</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Bits Per Sample --> + <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title">Select Preferred Bluetooth A2DP Codec Bits Per Sample</string> + + <!-- UI debug setting: Select Bluetooth Audio Channel Mode --> + <string name="bluetooth_select_a2dp_codec_channel_mode">Bluetooth Audio Channel Mode</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Channel Mode --> + <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title">Select Preferred Bluetooth A2DP Codec Channel Mode</string> + + <!-- UI debug setting: Select Bluetooth Audio LDAC Playback Quality --> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality">Bluetooth Audio LDAC Playback Quality</string> + <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec LDAC Playback Quality --> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Select Preferred Bluetooth A2DP Codec LDAC Playback Quality</string> + <!-- setting Checkbox summary whether to show options for wireless display certification --> <string name="wifi_display_certification_summary">Show options for wireless display certification</string> <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] --> diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index 5c8a6e25f6c2..a172e19ff750 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -358,6 +358,11 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private final TouchAnimator.Listener mNonFirstPageListener = new TouchAnimator.ListenerAdapter() { @Override + public void onAnimationAtEnd() { + mQuickQsPanel.setVisibility(View.INVISIBLE); + } + + @Override public void onAnimationStarted() { mQuickQsPanel.setVisibility(View.VISIBLE); } diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 36ef3e9f0433..4f43eac8b3ca 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -57,14 +57,16 @@ import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; + class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -137,16 +139,46 @@ class BluetoothManagerService extends IBluetoothManager.Stub { new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; + // used inside handler thread private boolean mQuietEnable = false; - // configuarion from external IBinder call which is used to + private boolean mEnable; + + /** + * Used for tracking apps that enabled / disabled Bluetooth. + */ + private class ActiveLog { + private String mPackageName; + private boolean mEnable; + private long mTimestamp; + + public ActiveLog(String packageName, boolean enable, long timestamp) { + mPackageName = packageName; + mEnable = enable; + mTimestamp = timestamp; + } + + public long getTime() { + return mTimestamp; + } + + public String toString() { + return android.text.format.DateFormat.format("MM-dd hh:mm:ss ", mTimestamp) + + (mEnable ? " Enabled " : " Disabled ") + " by " + mPackageName; + } + + } + + private LinkedList<ActiveLog> mActiveLogs; + + // configuration from external IBinder call which is used to // synchronize with broadcast receiver. private boolean mQuietEnableExternal; - // configuarion from external IBinder call which is used to - // synchronize with broadcast receiver. private boolean mEnableExternal; - // used inside handler thread - private boolean mEnable; + + // Map of apps registered to keep BLE scanning on. + private Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>(); + private int mState; private final BluetoothHandler mHandler; private int mErrorRecoveryRetryCounter; @@ -172,7 +204,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { + private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); @@ -251,12 +283,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } else if (st == BluetoothAdapter.STATE_ON){ // disable without persisting the setting Slog.d(TAG, "Calling disable"); - sendDisableMsg(); + sendDisableMsg("airplane mode"); } } else if (mEnableExternal) { // enable without persisting the setting Slog.d(TAG, "Calling enable"); - sendEnableMsg(mQuietEnableExternal); + sendEnableMsg(mQuietEnableExternal, "airplane mode"); } } } @@ -272,6 +304,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { || context.getResources().getBoolean( com.android.internal.R.bool.config_permissionReviewRequired); + mActiveLogs = new LinkedList<ActiveLog>(); mBluetooth = null; mBluetoothBinder = null; mBluetoothGatt = null; @@ -298,15 +331,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mEnableExternal = true; } - int sysUiUid = -1; + int systemUiUid = -1; try { - sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", + systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); } catch (PackageManager.NameNotFoundException e) { // Some platforms, such as wearables do not have a system ui. Slog.w(TAG, "Unable to resolve SystemUI's UID.", e); } - mSystemUiUid = sysUiUid; + mSystemUiUid = systemUiUid; } /** @@ -484,8 +517,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } class ClientDeathRecipient implements IBinder.DeathRecipient { + private String mPackageName; + + public ClientDeathRecipient(String packageName) { + mPackageName = packageName; + } + public void binderDied() { - if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App"); + if (DBG) Slog.d(TAG, "Binder is dead - unregister " + mPackageName); if (isBleAppPresent()) { // Nothing to do, another app is here. return; @@ -504,10 +543,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } } - } - /** Internal death rec list */ - Map<IBinder, ClientDeathRecipient> mBleApps = new ConcurrentHashMap<IBinder, ClientDeathRecipient>(); + public String getPackageName() { + return mPackageName; + } + } @Override public boolean isBleScanAlwaysAvailable() { @@ -565,28 +605,22 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public int updateBleAppCount(IBinder token, boolean enable) { - if (enable) { - ClientDeathRecipient r = mBleApps.get(token); - if (r == null) { - ClientDeathRecipient deathRec = new ClientDeathRecipient(); - try { - token.linkToDeath(deathRec, 0); - } catch (RemoteException ex) { - throw new IllegalArgumentException("Wake lock is already dead."); - } - mBleApps.put(token, deathRec); - if (DBG) Slog.d(TAG, "Registered for death Notification"); - } - - } else { - ClientDeathRecipient r = mBleApps.get(token); - if (r != null) { - // Unregister death recipient as the app goes away. - token.unlinkToDeath(r, 0); - mBleApps.remove(token); - if (DBG) Slog.d(TAG, "Unregistered for death Notification"); + public int updateBleAppCount(IBinder token, boolean enable, String packageName) { + ClientDeathRecipient r = mBleApps.get(token); + if (r == null && enable) { + ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); + try { + token.linkToDeath(deathRec, 0); + } catch (RemoteException ex) { + throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!"); } + mBleApps.put(token, deathRec); + if (DBG) Slog.d(TAG, "Registered for death of " + packageName); + } else if (!enable && r != null) { + // Unregister death recipient as the app goes away. + token.unlinkToDeath(r, 0); + mBleApps.remove(token); + if (DBG) Slog.d(TAG, "Unregistered for death of " + packageName); } int appCount = mBleApps.size(); if (DBG) Slog.d(TAG, appCount + " registered Ble Apps"); @@ -601,7 +635,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBleApps.clear(); } - /** @hide*/ + /** @hide */ public boolean isBleAppPresent() { if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size()); return mBleApps.size() > 0; @@ -667,7 +701,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public boolean enableNoAutoConnect() + public boolean enableNoAutoConnect(String packageName) { if (isBluetoothDisallowed()) { if (DBG) { @@ -692,7 +726,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized(mReceiver) { mQuietEnableExternal = true; mEnableExternal = true; - sendEnableMsg(true); + sendEnableMsg(true, packageName); } return true; } @@ -724,7 +758,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (DBG) { - Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth + + Slog.d(TAG,"enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = " + mBinding + " mState = " + BluetoothAdapter.nameForState(mState)); } @@ -733,7 +767,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mQuietEnableExternal = false; mEnableExternal = true; // waive WRITE_SECURE_SETTINGS permission check - sendEnableMsg(false); + sendEnableMsg(false, packageName); } if (DBG) Slog.d(TAG, "enable returning"); return true; @@ -768,7 +802,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { persistBluetoothSetting(BLUETOOTH_OFF); } mEnableExternal = false; - sendDisableMsg(); + sendDisableMsg(packageName); } return true; } @@ -909,7 +943,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); - sendEnableMsg(mQuietEnableExternal); + sendEnableMsg(mQuietEnableExternal, "system boot"); } else if (!isNameAndAddressSet()) { if (DBG) Slog.d(TAG, "Getting adapter name and address"); Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); @@ -1877,13 +1911,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } - private void sendDisableMsg() { + private void sendDisableMsg(String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); + addActiveLog(packageName, false); } - private void sendEnableMsg(boolean quietMode) { + private void sendEnableMsg(boolean quietMode, String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); + addActiveLog(packageName, true); + } + + private void addActiveLog(String packageName, boolean enable) { + synchronized (mActiveLogs) { + if (mActiveLogs.size() > 10) { + mActiveLogs.remove(); + } + mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis())); + } } private void recoverBluetoothServiceFromError(boolean clearBle) { @@ -1954,19 +1999,55 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); String errorMsg = null; + + boolean protoOut = (args.length > 0) && args[0].startsWith("--proto"); + + if (!protoOut) { + writer.println("Bluetooth Status"); + writer.println(" enabled: " + isEnabled()); + writer.println(" state: " + BluetoothAdapter.nameForState(mState)); + writer.println(" address: " + mAddress); + writer.println(" name: " + mName); + if (mEnable) { + long onDuration = System.currentTimeMillis() - mActiveLogs.getLast().getTime(); + String onDurationString = String.format("%02d:%02d:%02d.%03d", + (int)(onDuration / (1000 * 60 * 60)), + (int)((onDuration / (1000 * 60)) % 60), + (int)((onDuration / 1000) % 60), + (int)(onDuration % 1000)); + writer.println(" time since enabled: " + onDurationString + "\n"); + } + + writer.println("Enable log:"); + for (ActiveLog log : mActiveLogs) { + writer.println(log); + } + + writer.println("\n" + mBleApps.size() + " BLE Apps registered:"); + for (ClientDeathRecipient app : mBleApps.values()) { + writer.println(app.getPackageName()); + } + + writer.flush(); + if (args.length == 0) { + // Add arg to produce output + args = new String[1]; + args[0] = "--print"; + } + } + if (mBluetoothBinder == null) { errorMsg = "Bluetooth Service not connected"; } else { try { mBluetoothBinder.dump(fd, args); } catch (RemoteException re) { - errorMsg = "RemoteException while calling Bluetooth Service"; + errorMsg = "RemoteException while dumping Bluetooth Service"; } } if (errorMsg != null) { // Silently return if we are extracting metrics in Protobuf format - if ((args.length > 0) && args[0].startsWith("--proto")) - return; + if (protoOut) return; writer.println(errorMsg); } } diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 74ff41c13802..6296375525a4 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -154,7 +154,8 @@ option java_package com.android.server 3110 unknown_sources_enabled (value|1) # Package Manager critical info 3120 pm_critical_info (msg|3) - +# Disk usage stats for verifying quota correctness +3121 pm_package_stats (manual_time|2|3),(quota_time|2|3),(manual_data|2|2),(quota_data|2|2),(manual_cache|2|2),(quota_cache|2|2) # --------------------------- # WindowManagerService.java diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index b9a483138520..4cc293125bcc 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -46,6 +46,7 @@ import android.content.pm.ProviderInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.ObbInfo; +import android.net.TrafficStats; import android.net.Uri; import android.os.Binder; import android.os.DropBoxManager; @@ -86,6 +87,7 @@ import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Log; +import android.util.Pair; import android.util.Slog; import android.util.TimeUtils; import android.util.Xml; @@ -3738,6 +3740,18 @@ class MountService extends IMountService.Stub pw.println(); pw.println("Primary storage UUID: " + mPrimaryStorageUuid); + final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize(); + if (pair == null) { + pw.println("Internal storage total size: N/A"); + } else { + pw.print("Internal storage ("); + pw.print(pair.first); + pw.print(") total size: "); + pw.print(pair.second); + pw.print(" ("); + pw.print((float) pair.second / TrafficStats.GB_IN_BYTES); + pw.println(" GB)"); + } pw.println("Force adoptable: " + mForceAdoptable); pw.println(); pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers)); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5b02c7916354..bc0390119a1d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3729,13 +3729,14 @@ public final class ActivityManagerService extends ActivityManagerNative * resources like shared libraries and access user-wide resources */ if (ArrayUtils.isEmpty(permGids)) { - gids = new int[2]; + gids = new int[3]; } else { - gids = new int[permGids.length + 2]; - System.arraycopy(permGids, 0, gids, 2, permGids.length); + gids = new int[permGids.length + 3]; + System.arraycopy(permGids, 0, gids, 3, permGids.length); } gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); - gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid)); + gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid)); + gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid)); } checkTime(startTime, "startProcess: building args"); if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 7fe6c3e0a332..5d619c11ba44 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -225,6 +225,7 @@ public class AudioService extends IAudioService.Stub { private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100; private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101; private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102; + private static final int MSG_A2DP_DEVICE_CONFIG_CHANGE = 103; // end of messages handled under wakelock private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; @@ -3146,7 +3147,7 @@ public class AudioService extends IAudioService.Stub { queueMsgUnderWakeLock(mAudioHandler, MSG_SET_A2DP_SINK_CONNECTION_STATE, state, - 0, + 0 /* arg2 unused */, btDevice, delay); } @@ -3163,7 +3164,7 @@ public class AudioService extends IAudioService.Stub { queueMsgUnderWakeLock(mAudioHandler, MSG_SET_A2DP_SRC_CONNECTION_STATE, state, - 0, + 0 /* arg2 unused */, btDevice, 0 /* delay */); } @@ -3809,8 +3810,8 @@ public class AudioService extends IAudioService.Stub { int delay = checkSendBecomingNoisyIntent(type, state); queueMsgUnderWakeLock(mAudioHandler, MSG_SET_WIRED_DEVICE_CONNECTION_STATE, - 0, - 0, + 0 /* arg1 unused */, + 0 /* arg2 unused */, new WiredDeviceConnectionState(type, state, address, name, caller), delay); } @@ -3833,13 +3834,25 @@ public class AudioService extends IAudioService.Stub { (profile == BluetoothProfile.A2DP ? MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE), state, - 0, + 0 /* arg2 unused */, device, delay); } return delay; } + public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device) + { + synchronized (mConnectedDevices) { + queueMsgUnderWakeLock(mAudioHandler, + MSG_A2DP_DEVICE_CONFIG_CHANGE, + 0 /* arg1 unused */, + 0 /* arg1 unused */, + device, + 0 /* delay */); + } + } + /////////////////////////////////////////////////////////////////////////// // Inner classes /////////////////////////////////////////////////////////////////////////// @@ -4644,6 +4657,11 @@ public class AudioService extends IAudioService.Stub { mAudioEventWakeLock.release(); break; + case MSG_A2DP_DEVICE_CONFIG_CHANGE: + onBluetoothA2dpDeviceConfigChange((BluetoothDevice)msg.obj); + mAudioEventWakeLock.release(); + break; + case MSG_REPORT_NEW_ROUTES: { int N = mRoutesObservers.beginBroadcast(); if (N > 0) { @@ -4866,7 +4884,7 @@ public class AudioService extends IAudioService.Stub { private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state) { if (DEBUG_VOL) { - Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state); + Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice+"state=" + state); } if (btDevice == null) { return; @@ -4877,9 +4895,9 @@ public class AudioService extends IAudioService.Stub { } synchronized (mConnectedDevices) { - String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, - btDevice.getAddress()); - DeviceListSpec deviceSpec = mConnectedDevices.get(key); + final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + btDevice.getAddress()); + final DeviceListSpec deviceSpec = mConnectedDevices.get(key); boolean isConnected = deviceSpec != null; if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { @@ -4930,7 +4948,7 @@ public class AudioService extends IAudioService.Stub { private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state) { if (DEBUG_VOL) { - Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state); + Log.d(TAG, "onSetA2dpSourceConnectionState btDevice=" + btDevice + " state=" + state); } if (btDevice == null) { return; @@ -4941,8 +4959,8 @@ public class AudioService extends IAudioService.Stub { } synchronized (mConnectedDevices) { - String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address); - DeviceListSpec deviceSpec = mConnectedDevices.get(key); + final String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address); + final DeviceListSpec deviceSpec = mConnectedDevices.get(key); boolean isConnected = deviceSpec != null; if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { @@ -4953,6 +4971,31 @@ public class AudioService extends IAudioService.Stub { } } + private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice) + { + if (DEBUG_VOL) { + Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice); + } + if (btDevice == null) { + return; + } + String address = btDevice.getAddress(); + if (!BluetoothAdapter.checkBluetoothAddress(address)) { + address = ""; + } + + int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; + synchronized (mConnectedDevices) { + final String key = makeDeviceListKey(device, address); + final DeviceListSpec deviceSpec = mConnectedDevices.get(key); + if (deviceSpec != null) { + // Device is connected + AudioSystem.handleDeviceConfigChange(device, address, + btDevice.getName()); + } + } + } + public void avrcpSupportsAbsoluteVolume(String address, boolean support) { // address is not used for now, but may be used when multiple a2dp devices are supported synchronized (mA2dpAvrcpLock) { diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index 5016ec0d4be0..a6f9243887df 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -1013,7 +1013,7 @@ final class DefaultPermissionGrantPolicy { permissions.clear(); } permissions.add(permissionGrant.name); - grantRuntimePermissionsLPw(pkg, permissions, false, + grantRuntimePermissionsLPw(pkg, permissions, permissionGrant.fixed, userId); } } diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 1f83d9e9230d..605fa5d8d0c3 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -54,6 +54,7 @@ public class Installer extends SystemService { // NOTE: keep in sync with installd public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; + public static final int FLAG_USE_QUOTA = 1 << 12; private final boolean mIsolated; @@ -198,12 +199,13 @@ public class Installer extends SystemService { } } - public void getAppSize(String uuid, String packageName, int userId, int flags, long ceDataInode, - String codePath, PackageStats stats) throws InstallerException { + public void getAppSize(String uuid, String packageName, int userId, int flags, int appId, + long ceDataInode, String codePath, String externalUuid, PackageStats stats) + throws InstallerException { if (!checkBeforeRemote()) return; try { - final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, ceDataInode, - codePath); + final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, appId, + ceDataInode, codePath, externalUuid); stats.codeSize += res[0]; stats.dataSize += res[1]; stats.cacheSize += res[2]; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7ce5aa8ae39d..614230c273dd 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -370,6 +370,9 @@ public class PackageManagerService extends IPackageManager.Stub { private static final boolean DISABLE_EPHEMERAL_APPS = false; private static final boolean HIDE_EPHEMERAL_APIS = true; + private static final boolean ENABLE_QUOTA = + SystemProperties.getBoolean("persist.fw.quota", false); + private static final int RADIO_UID = Process.PHONE_UID; private static final int LOG_UID = Process.LOG_UID; private static final int NFC_UID = Process.NFC_UID; @@ -16869,6 +16872,11 @@ public class PackageManagerService extends IPackageManager.Stub { mHandler.sendMessage(msg); } + private boolean equals(PackageStats a, PackageStats b) { + return (a.codeSize == b.codeSize) && (a.dataSize == b.dataSize) + && (a.cacheSize == b.cacheSize); + } + private boolean getPackageSizeInfoLI(String packageName, int userId, PackageStats stats) { final PackageSetting ps; synchronized (mPackages) { @@ -16878,20 +16886,51 @@ public class PackageManagerService extends IPackageManager.Stub { return false; } } + + final long ceDataInode = ps.getCeDataInode(userId); + final PackageStats quotaStats = new PackageStats(stats.packageName, stats.userHandle); + + final StorageManager storage = mContext.getSystemService(StorageManager.class); + final String externalUuid = storage.getPrimaryStorageUuid(); try { - mInstaller.getAppSize(ps.volumeUuid, packageName, userId, - StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE, - ps.getCeDataInode(userId), ps.codePathString, stats); + final long start = SystemClock.elapsedRealtimeNanos(); + mInstaller.getAppSize(ps.volumeUuid, packageName, userId, 0, + ps.appId, ceDataInode, ps.codePathString, externalUuid, stats); + final long stopManual = SystemClock.elapsedRealtimeNanos(); + if (ENABLE_QUOTA) { + mInstaller.getAppSize(ps.volumeUuid, packageName, userId, Installer.FLAG_USE_QUOTA, + ps.appId, ceDataInode, ps.codePathString, externalUuid, quotaStats); + } + final long stopQuota = SystemClock.elapsedRealtimeNanos(); + + // For now, ignore code size of packages on system partition + if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) { + stats.codeSize = 0; + quotaStats.codeSize = 0; + } + + if (ENABLE_QUOTA && Build.IS_ENG && !ps.isSharedUser()) { + if (!equals(stats, quotaStats)) { + Log.w(TAG, "Found discrepancy between statistics:"); + Log.w(TAG, "Manual: " + stats); + Log.w(TAG, "Quota: " + quotaStats); + } + final long manualTime = stopManual - start; + final long quotaTime = stopQuota - stopManual; + EventLogTags.writePmPackageStats(manualTime, quotaTime, + stats.dataSize, quotaStats.dataSize, + stats.cacheSize, quotaStats.cacheSize); + } + + // External clients expect these to be tracked separately + stats.dataSize -= stats.cacheSize; + quotaStats.dataSize -= quotaStats.cacheSize; + } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); return false; } - // For now, ignore code size of packages on system partition - if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) { - stats.codeSize = 0; - } - return true; } diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index 69d27f292072..9a9f81e03dfd 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -53,6 +53,7 @@ import android.content.res.Resources; import android.net.INetworkRecommendationProvider; import android.net.INetworkScoreCache; import android.net.NetworkKey; +import android.net.NetworkScoreManager; import android.net.NetworkScorerAppManager; import android.net.NetworkScorerAppManager.NetworkScorerAppData; import android.net.RecommendationRequest; @@ -134,9 +135,10 @@ public class NetworkScoreServiceTest { mNetworkScoreService.systemRunning(); - verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent( - new ComponentName(NEW_SCORER.packageName, - NEW_SCORER.recommendationServiceClassName))), + verify(mContext).bindServiceAsUser(MockUtils.checkIntent( + new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS) + .setComponent(new ComponentName(NEW_SCORER.packageName, + NEW_SCORER.recommendationServiceClassName))), any(ServiceConnection.class), eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE), eq(UserHandle.SYSTEM)); diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index 03342548e7df..811c99602599 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -233,6 +233,13 @@ public class DisconnectCause { */ public static final int DIALED_ON_WRONG_SLOT = 56; + /** + * The network does not accept the emergency call request because IMEI was used as + * identification and this cability is not supported by the network. + * {@hide} + */ + public static final int IMEI_NOT_ACCEPTED = 57; + //********************************************************************************************* // When adding a disconnect type: // 1) Please assign the new type the next id value below. @@ -241,14 +248,14 @@ public class DisconnectCause { // 4) Update toString() with the newly added disconnect type. // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause. // - // NextId: 57 + // NextId: 58 //********************************************************************************************* /** Smallest valid value for call disconnect codes. */ public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED; /** Largest valid value for call disconnect codes. */ - public static final int MAXIMUM_VALID_VALUE = DIALED_ON_WRONG_SLOT; + public static final int MAXIMUM_VALID_VALUE = IMEI_NOT_ACCEPTED; /** Private constructor to avoid class instantiation. */ private DisconnectCause() { @@ -370,6 +377,8 @@ public class DisconnectCause { return "DATA_LIMIT_REACHED"; case DIALED_ON_WRONG_SLOT: return "DIALED_ON_WRONG_SLOT"; + case IMEI_NOT_ACCEPTED: + return "IMEI_NOT_ACCEPTED"; default: return "INVALID: " + cause; } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 9e897bff1122..18c124503136 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -59,7 +59,7 @@ interface IWifiManager int addOrUpdateNetwork(in WifiConfiguration config); - boolean addPasspointConfiguration(in PasspointConfiguration config); + boolean addOrUpdatePasspointConfiguration(in PasspointConfiguration config); boolean removePasspointConfiguration(in String fqdn); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 674c16156cc8..618a7192a612 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -842,31 +842,31 @@ public class WifiManager { } /** - * Add a Passpoint configuration. The configuration provides a credential + * Add or update a Passpoint configuration. The configuration provides a credential * for connecting to Passpoint networks that are operated by the Passpoint * service provider specified in the configuration. * * Each configuration is uniquely identified by its FQDN (Fully Qualified Domain - * Name). In the case when there is an existing configuration with the same base - * domain, the new configuration will replace the existing configuration. + * Name). In the case when there is an existing configuration with the same + * FQDN, the new configuration will replace the existing configuration. * * @param config The Passpoint configuration to be added - * @return true on success or false on failure + * @return true on success * @hide */ - public boolean addPasspointConfiguration(PasspointConfiguration config) { + public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) { try { - return mService.addPasspointConfiguration(config); + return mService.addOrUpdatePasspointConfiguration(config); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Remove a Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). + * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). * * @param fqdn The FQDN of the passpoint configuration to be removed - * @return true on success or false on failure + * @return true on success * @hide */ public boolean removePasspointConfiguration(String fqdn) { @@ -880,7 +880,9 @@ public class WifiManager { /** * Return the list of installed Passpoint configurations. * - * @return A list of PasspointConfiguration or null + * An empty list will be returned when no configurations are installed. + * + * @return A list of {@link PasspointConfiguration} * @hide */ public List<PasspointConfiguration> getPasspointConfigurations() { diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java b/wifi/java/android/net/wifi/aware/AttachCallback.java index 1e8dbd945b6e..90216f3f71d3 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java +++ b/wifi/java/android/net/wifi/aware/AttachCallback.java @@ -18,16 +18,16 @@ package android.net.wifi.aware; /** * Base class for Aware attach callbacks. Should be extended by applications and set when calling - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}. These are callbacks + * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}. These are callbacks * applying to the Aware connection as a whole - not to specific publish or subscribe sessions - - * for that see {@link WifiAwareDiscoverySessionCallback}. + * for that see {@link DiscoverySessionCallback}. * * @hide PROPOSED_AWARE_API */ -public class WifiAwareAttachCallback { +public class AttachCallback { /** * Called when Aware attach operation - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)} + * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)} * is completed and that we can now start discovery sessions or connections. * * @param session The Aware object on which we can execute further Aware operations - e.g. @@ -39,7 +39,7 @@ public class WifiAwareAttachCallback { /** * Called when Aware attach operation - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)} failed. + * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)} failed. */ public void onAttachFailed() { /* empty */ diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl b/wifi/java/android/net/wifi/aware/Characteristics.aidl index a35e71dada09..77305e9dae0a 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl +++ b/wifi/java/android/net/wifi/aware/Characteristics.aidl @@ -16,4 +16,4 @@ package android.net.wifi.aware; -parcelable WifiAwareCharacteristics; +parcelable Characteristics; diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java b/wifi/java/android/net/wifi/aware/Characteristics.java index 092aa341c9b3..1c3e39025439 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java +++ b/wifi/java/android/net/wifi/aware/Characteristics.java @@ -25,7 +25,7 @@ import android.os.Parcelable; * * @hide PROPOSED_AWARE_API */ -public class WifiAwareCharacteristics implements Parcelable { +public class Characteristics implements Parcelable { /** @hide */ public static final String KEY_MAX_SERVICE_NAME_LENGTH = "key_max_service_name_length"; /** @hide */ @@ -37,7 +37,7 @@ public class WifiAwareCharacteristics implements Parcelable { private Bundle mCharacteristics = new Bundle(); /** @hide : should not be created by apps */ - public WifiAwareCharacteristics(Bundle characteristics) { + public Characteristics(Bundle characteristics) { mCharacteristics = characteristics; } @@ -58,7 +58,7 @@ public class WifiAwareCharacteristics implements Parcelable { * message exchange. Restricts the parameters of the * {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])}, * {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}, and - * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])} + * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} * variants. * * @return A positive integer, maximum length of byte array for Aware messaging. @@ -89,17 +89,17 @@ public class WifiAwareCharacteristics implements Parcelable { return 0; } - public static final Creator<WifiAwareCharacteristics> CREATOR = - new Creator<WifiAwareCharacteristics>() { + public static final Creator<Characteristics> CREATOR = + new Creator<Characteristics>() { @Override - public WifiAwareCharacteristics createFromParcel(Parcel in) { - WifiAwareCharacteristics c = new WifiAwareCharacteristics(in.readBundle()); + public Characteristics createFromParcel(Parcel in) { + Characteristics c = new Characteristics(in.readBundle()); return c; } @Override - public WifiAwareCharacteristics[] newArray(int size) { - return new WifiAwareCharacteristics[size]; + public Characteristics[] newArray(int size) { + return new Characteristics[size]; } }; } diff --git a/wifi/java/android/net/wifi/aware/ConfigRequest.java b/wifi/java/android/net/wifi/aware/ConfigRequest.java index 4b21b15d4994..6a5957badafb 100644 --- a/wifi/java/android/net/wifi/aware/ConfigRequest.java +++ b/wifi/java/android/net/wifi/aware/ConfigRequest.java @@ -22,7 +22,7 @@ import android.os.Parcelable; /** * Defines a request object to configure a Wi-Fi Aware network. Built using * {@link ConfigRequest.Builder}. Configuration is requested using - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}. + * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}. * Note that the actual achieved configuration may be different from the * requested configuration - since different applications may request different * configurations. diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java index 2812ad4f147d..c89718f8b132 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java @@ -29,21 +29,21 @@ import java.lang.ref.WeakReference; /** * A class representing a single publish or subscribe Aware session. This object * will not be created directly - only its child classes are available: - * {@link WifiAwarePublishDiscoverySession} and {@link WifiAwareSubscribeDiscoverySession}. This + * {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This * class provides functionality common to both publish and subscribe discovery sessions: * <ul> - * <li>Sending messages: {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[])} or - * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)} methods. + * <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} or + * {@link #sendMessage(PeerHandle, int, byte[], int)} methods. * <li>Creating a network-specifier when requesting a Aware connection: - * {@link #createNetworkSpecifier(WifiAwareManager.PeerHandle, byte[])}. + * {@link #createNetworkSpecifier(PeerHandle, byte[])}. * </ul> * The {@link #destroy()} method must be called to destroy discovery sessions once they are * no longer needed. * * @hide PROPOSED_AWARE_API */ -public class WifiAwareDiscoveryBaseSession { - private static final String TAG = "WifiAwareDiscBaseSsn"; +public class DiscoverySession { + private static final String TAG = "DiscoverySession"; private static final boolean DBG = false; private static final boolean VDBG = false; // STOPSHIP if true @@ -62,7 +62,7 @@ public class WifiAwareDiscoveryBaseSession { /** * Return the maximum permitted retry count when sending messages using - * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}. + * {@link #sendMessage(PeerHandle, int, byte[], int)}. * * @return Maximum retry count when sending messages. */ @@ -71,7 +71,7 @@ public class WifiAwareDiscoveryBaseSession { } /** @hide */ - public WifiAwareDiscoveryBaseSession(WifiAwareManager manager, int clientId, int sessionId) { + public DiscoverySession(WifiAwareManager manager, int clientId, int sessionId) { if (VDBG) { Log.v(TAG, "New discovery session created: manager=" + manager + ", clientId=" + clientId + ", sessionId=" + sessionId); @@ -93,7 +93,7 @@ public class WifiAwareDiscoveryBaseSession { * This operation must be done on a session which is no longer needed. Otherwise system * resources will continue to be utilized until the application exits. The only * exception is a session for which we received a termination callback, - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}. + * {@link DiscoverySessionCallback#onSessionTerminated()}. */ public void destroy() { WifiAwareManager mgr = mMgr.get(); @@ -139,23 +139,23 @@ public class WifiAwareDiscoveryBaseSession { /** * Sends a message to the specified destination. Aware messages are transmitted in the context * of a discovery session - executed subsequent to a publish/subscribe - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} event. * <p> * Aware messages are not guaranteed delivery. Callbacks on - * {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully, - * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission + * {@link DiscoverySessionCallback} indicate message was transmitted successfully, + * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission * failed (possibly after several retries) - - * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}. + * {@link DiscoverySessionCallback#onMessageSendFailed(int)}. * <p> * The peer will get a callback indicating a message was received using - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])}. * * @param peerHandle The peer's handle for the message. Must be a result of an - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} or - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])} events. * @param messageId An arbitrary integer used by the caller to identify the message. The same * integer ID will be returned in the callbacks indicating message send success or @@ -167,7 +167,7 @@ public class WifiAwareDiscoveryBaseSession { * (note: no retransmissions are attempted in other failure cases). A value of 0 * indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}. */ - public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId, + public void sendMessage(@NonNull PeerHandle peerHandle, int messageId, @Nullable byte[] message, int retryCount) { if (mTerminated) { Log.w(TAG, "sendMessage: called on terminated session"); @@ -186,25 +186,25 @@ public class WifiAwareDiscoveryBaseSession { /** * Sends a message to the specified destination. Aware messages are transmitted in the context * of a discovery session - executed subsequent to a publish/subscribe - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} event. * <p> * Aware messages are not guaranteed delivery. Callbacks on - * {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully, - * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission + * {@link DiscoverySessionCallback} indicate message was transmitted successfully, + * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission * failed (possibly after several retries) - - * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}. + * {@link DiscoverySessionCallback#onMessageSendFailed(int)}. * <p> * The peer will get a callback indicating a message was received using - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])}. - * Equivalent to {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)} + * Equivalent to {@link #sendMessage(PeerHandle, int, byte[], int)} * with a {@code retryCount} of 0. * * @param peerHandle The peer's handle for the message. Must be a result of an - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} or - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])} events. * @param messageId An arbitrary integer used by the caller to identify the message. The same * integer ID will be returned in the callbacks indicating message send success or @@ -212,16 +212,16 @@ public class WifiAwareDiscoveryBaseSession { * can be arbitrary and non-unique. * @param message The message to be transmitted. */ - public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId, + public void sendMessage(@NonNull PeerHandle peerHandle, int messageId, @Nullable byte[] message) { sendMessage(peerHandle, messageId, message, 0); } /** * Start a ranging operation with the specified peers. The peer IDs are obtained from an - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} or - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])} operation - can * only range devices which are part of an ongoing discovery session. * @@ -265,9 +265,9 @@ public class WifiAwareDiscoveryBaseSession { * and a Publisher is a RESPONDER. * * @param peerHandle The peer's handle obtained through - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, * byte[], java.util.List)} or - * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle, + * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request * from only that peer. A RESPONDER may specified a null - indicating that * it will accept connection requests from any device. @@ -283,7 +283,7 @@ public class WifiAwareDiscoveryBaseSession { * android.net.ConnectivityManager.NetworkCallback)} * [or other varieties of that API]. */ - public String createNetworkSpecifier(@Nullable WifiAwareManager.PeerHandle peerHandle, + public String createNetworkSpecifier(@Nullable PeerHandle peerHandle, @Nullable byte[] token) { if (mTerminated) { Log.w(TAG, "createNetworkSpecifier: called on terminated session"); @@ -295,7 +295,7 @@ public class WifiAwareDiscoveryBaseSession { return null; } - int role = this instanceof WifiAwareSubscribeDiscoverySession + int role = this instanceof SubscribeDiscoverySession ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java index fdf0d013334d..1fe449fc1115 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java @@ -16,79 +16,53 @@ package android.net.wifi.aware; -import android.annotation.IntDef; import android.annotation.NonNull; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.List; /** * Base class for Aware session events callbacks. Should be extended by * applications wanting notifications. The callbacks are set when a * publish or subscribe session is created using - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} or - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * android.os.Handler)}. * <p> * A single callback is set at session creation - it cannot be replaced. * * @hide PROPOSED_AWARE_API */ -public class WifiAwareDiscoverySessionCallback { - /** @hide */ - @IntDef({ - TERMINATE_REASON_DONE, TERMINATE_REASON_FAIL }) - @Retention(RetentionPolicy.SOURCE) - public @interface SessionTerminateCodes { - } - - /** - * Indicates that publish or subscribe session is done - all the - * requested operations (per {@link PublishConfig} or - * {@link SubscribeConfig}) have been executed. Failure reason flag for - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback. - */ - public static final int TERMINATE_REASON_DONE = 100; - - /** - * Indicates that publish or subscribe session is terminated due to a - * failure. - * Failure reason flag for - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback. - */ - public static final int TERMINATE_REASON_FAIL = 101; - +public class DiscoverySessionCallback { /** * Called when a publish operation is started successfully in response to a - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} operation. * - * @param session The {@link WifiAwarePublishDiscoverySession} used to control the + * @param session The {@link PublishDiscoverySession} used to control the * discovery session. */ - public void onPublishStarted(@NonNull WifiAwarePublishDiscoverySession session) { + public void onPublishStarted(@NonNull PublishDiscoverySession session) { /* empty */ } /** * Called when a subscribe operation is started successfully in response to a - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * android.os.Handler)} operation. * - * @param session The {@link WifiAwareSubscribeDiscoverySession} used to control the + * @param session The {@link SubscribeDiscoverySession} used to control the * discovery session. */ - public void onSubscribeStarted(@NonNull WifiAwareSubscribeDiscoverySession session) { + public void onSubscribeStarted(@NonNull SubscribeDiscoverySession session) { /* empty */ } /** * Called when a publish or subscribe discovery session configuration update request * succeeds. Called in response to - * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * {@link PublishDiscoverySession#updatePublish(PublishConfig)} or + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. */ public void onSessionConfigUpdated() { /* empty */ @@ -96,12 +70,12 @@ public class WifiAwareDiscoverySessionCallback { /** * Called when a publish or subscribe discovery session cannot be created: - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} or - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * android.os.Handler)}, or when a configuration update fails: - * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * {@link PublishDiscoverySession#updatePublish(PublishConfig)} or + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. * <p> * For discovery session updates failure leaves the session running with its previous * configuration - the discovery session is not terminated. @@ -112,14 +86,11 @@ public class WifiAwareDiscoverySessionCallback { /** * Called when a discovery session (publish or subscribe) terminates. Termination may be due - * to user-request (either directly through {@link WifiAwareDiscoveryBaseSession#destroy()} or + * to user-request (either directly through {@link DiscoverySession#destroy()} or * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)} - * or {@link SubscribeConfig.Builder#setTtlSec(int)}) or due to a failure. - * - * @param reason The termination reason using - * {@code WifiAwareDiscoverySessionCallback.TERMINATE_*} codes. + * or {@link SubscribeConfig.Builder#setTtlSec(int)}). */ - public void onSessionTerminated(@SessionTerminateCodes int reason) { + public void onSessionTerminated() { /* empty */ } @@ -133,19 +104,19 @@ public class WifiAwareDiscoverySessionCallback { * configuration. * @param matchFilter The filter which resulted in this service discovery. */ - public void onServiceDiscovered(WifiAwareManager.PeerHandle peerHandle, + public void onServiceDiscovered(PeerHandle peerHandle, byte[] serviceSpecificInfo, List<byte[]> matchFilter) { /* empty */ } /** * Called in response to - * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])} + * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} * when a message is transmitted successfully - i.e. when it was received successfully by the * peer (corresponds to an ACK being received). * <p> * Note that either this callback or - * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)} will be + * {@link DiscoverySessionCallback#onMessageSendFailed(int)} will be * received - never both. * * @param messageId The arbitrary message ID specified when sending the message. @@ -157,11 +128,11 @@ public class WifiAwareDiscoverySessionCallback { /** * Called when message transmission fails - when no ACK is received from the peer. * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using - * the {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, + * the {@link DiscoverySession#sendMessage(PeerHandle, int, * byte[], int)} method) - this event is received after all retries are exhausted. * <p> * Note that either this callback or - * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)} will be received + * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)} will be received * - never both. * * @param messageId The arbitrary message ID specified when sending the message. @@ -172,14 +143,14 @@ public class WifiAwareDiscoverySessionCallback { /** * Called when a message is received from a discovery session peer - in response to the - * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, - * byte[])} or {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, + * peer's {@link DiscoverySession#sendMessage(PeerHandle, int, + * byte[])} or {@link DiscoverySession#sendMessage(PeerHandle, * int, byte[], int)}. * * @param peerHandle An opaque handle to the peer matching our discovery operation. * @param message A byte array containing the message. */ - public void onMessageReceived(WifiAwareManager.PeerHandle peerHandle, byte[] message) { + public void onMessageReceived(PeerHandle peerHandle, byte[] message) { /* empty */ } } diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl index 9c92807c63b5..794c142775f3 100644 --- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl +++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl @@ -23,7 +23,7 @@ import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; import android.net.wifi.aware.IWifiAwareEventCallback; import android.net.wifi.aware.PublishConfig; import android.net.wifi.aware.SubscribeConfig; -import android.net.wifi.aware.WifiAwareCharacteristics; +import android.net.wifi.aware.Characteristics; import android.net.wifi.RttManager; /** @@ -37,7 +37,7 @@ interface IWifiAwareManager void enableUsage(); void disableUsage(); boolean isUsageEnabled(); - WifiAwareCharacteristics getCharacteristics(); + Characteristics getCharacteristics(); // client API void connect(in IBinder binder, in String callingPackage, in IWifiAwareEventCallback callback, diff --git a/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java index e8f52cd4bdeb..b0f97bda0339 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java +++ b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java @@ -28,7 +28,7 @@ package android.net.wifi.aware; * * @hide PROPOSED_AWARE_API */ -public class WifiAwareIdentityChangedListener { +public class IdentityChangedListener { /** * @param mac The MAC address of the Aware discovery interface. The application must have the * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to get the actual MAC address, diff --git a/wifi/java/android/net/wifi/aware/PeerHandle.java b/wifi/java/android/net/wifi/aware/PeerHandle.java new file mode 100644 index 000000000000..777d9a376fdf --- /dev/null +++ b/wifi/java/android/net/wifi/aware/PeerHandle.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 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.net.wifi.aware; + +/** + * Opaque object used to represent a Wi-Fi Aware peer. Obtained from discovery sessions in + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}, used + * when sending messages e,g, {@link PublishDiscoverySession#sendMessage(PeerHandle, int, byte[])}, + * or when configuring a network link to a peer, e.g. + * {@link PublishDiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}. + * + * @hide PROPOSED_AWARE_API + */ +public class PeerHandle { + /** @hide */ + public PeerHandle(int peerId) { + this.peerId = peerId; + } + + /** @hide */ + public int peerId; +} diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java index 3925bd71ab9e..1b8ef8431f19 100644 --- a/wifi/java/android/net/wifi/aware/PublishConfig.java +++ b/wifi/java/android/net/wifi/aware/PublishConfig.java @@ -33,9 +33,9 @@ import java.util.List; /** * Defines the configuration of a Aware publish session. Built using * {@link PublishConfig.Builder}. A publish session is created using - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} or updated using - * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}. + * {@link PublishDiscoverySession#updatePublish(PublishConfig)}. * * @hide PROPOSED_AWARE_API */ @@ -184,7 +184,7 @@ public final class PublishConfig implements Parcelable { * * @hide */ - public void assertValid(WifiAwareCharacteristics characteristics) + public void assertValid(Characteristics characteristics) throws IllegalArgumentException { WifiAwareUtils.validateServiceName(mServiceName); @@ -322,12 +322,11 @@ public final class PublishConfig implements Parcelable { * Sets the number of times an unsolicited (configured using * {@link PublishConfig.Builder#setPublishType(int)}) publish session * will be broadcast. When the count is reached an event will be - * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} - * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless - * {@link #setTerminateNotificationEnabled(boolean)} disables the callback]. + * generated for {@link DiscoverySessionCallback#onSessionTerminated()} + * [unless {@link #setTerminateNotificationEnabled(boolean)} disables the callback]. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is + * Session will be terminated when {@link DiscoverySession#destroy()} is * called. * * @param publishCount Number of publish packets to broadcast. @@ -348,12 +347,11 @@ public final class PublishConfig implements Parcelable { * {@link PublishConfig.Builder#setPublishType(int)}) publish session * will be alive - broadcasting a packet. When the TTL is reached * an event will be generated for - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with - * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless + * {@link DiscoverySessionCallback#onSessionTerminated()} [unless * {@link #setTerminateNotificationEnabled(boolean)} disables the callback]. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is + * Session will be terminated when {@link DiscoverySession#destroy()} is * called. * * @param ttlSec Lifetime of a publish session in seconds. @@ -371,7 +369,7 @@ public final class PublishConfig implements Parcelable { /** * Configure whether a publish terminate notification - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported + * {@link DiscoverySessionCallback#onSessionTerminated()} is reported * back to the callback. * * @param enable If true the terminate callback will be called when the diff --git a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java b/wifi/java/android/net/wifi/aware/PublishDiscoverySession.java index 68786d17d38d..f2355b382e8d 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java +++ b/wifi/java/android/net/wifi/aware/PublishDiscoverySession.java @@ -21,32 +21,32 @@ import android.util.Log; /** * A class representing a Aware publish session. Created when - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, * android.os.Handler)} is called and a discovery session is created and returned in - * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}. See - * baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. This + * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)}. See + * baseline functionality of all discovery sessions in {@link DiscoverySession}. This * object allows updating an existing/running publish discovery session using * {@link #updatePublish(PublishConfig)}. * * @hide PROPOSED_AWARE_API */ -public class WifiAwarePublishDiscoverySession extends WifiAwareDiscoveryBaseSession { - private static final String TAG = "WifiAwarePublishDiscSsn"; +public class PublishDiscoverySession extends DiscoverySession { + private static final String TAG = "PublishDiscoverySession"; /** @hide */ - public WifiAwarePublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) { + public PublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) { super(manager, clientId, sessionId); } /** * Re-configure the currently active publish session. The - * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used + * {@link DiscoverySessionCallback} is not replaced - the same listener used * at creation is still used. The results of the configuration are returned using - * {@link WifiAwareDiscoverySessionCallback}: + * {@link DiscoverySessionCallback}: * <ul> - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration + * <li>{@link DiscoverySessionCallback#onSessionConfigUpdated()}: configuration * update succeeded. - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration + * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()}: configuration * update failed. The publish discovery session is still running using its previous * configuration (i.e. update failure does not terminate the session). * </ul> diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java index 0fe69a81d218..a54a4f5f5131 100644 --- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java +++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java @@ -33,9 +33,9 @@ import java.util.List; /** * Defines the configuration of a Aware subscribe session. Built using * {@link SubscribeConfig.Builder}. Subscribe is done using - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * android.os.Handler)} or - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. * * @hide PROPOSED_AWARE_API */ @@ -212,7 +212,7 @@ public final class SubscribeConfig implements Parcelable { * * @hide */ - public void assertValid(WifiAwareCharacteristics characteristics) + public void assertValid(Characteristics characteristics) throws IllegalArgumentException { WifiAwareUtils.validateServiceName(mServiceName); @@ -355,11 +355,10 @@ public final class SubscribeConfig implements Parcelable { * Sets the number of times an active ( * {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session * will broadcast. When the count is reached an event will be - * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} - * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}. + * generated for {@link DiscoverySessionCallback#onSessionTerminated()}. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is + * Session will be terminated when {@link DiscoverySession#destroy()} is * called. * * @param subscribeCount Number of subscribe packets to broadcast. @@ -380,11 +379,10 @@ public final class SubscribeConfig implements Parcelable { * {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session * will be alive - i.e. broadcasting a packet. When the TTL is reached * an event will be generated for - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with - * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}. + * {@link DiscoverySessionCallback#onSessionTerminated()}. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is + * Session will be terminated when {@link DiscoverySession#destroy()} is * called. * * @param ttlSec Lifetime of a subscribe session in seconds. @@ -404,8 +402,8 @@ public final class SubscribeConfig implements Parcelable { * Sets the match style of the subscription - how are matches from a * single match session (corresponding to the same publish action on the * peer) reported to the host (using the - * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle, - * byte[], List)}). The options are: only report the first match and ignore the rest + * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], + * java.util.List)}). The options are: only report the first match and ignore the rest * {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single * match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default). * @@ -424,7 +422,7 @@ public final class SubscribeConfig implements Parcelable { /** * Configure whether a subscribe terminate notification - * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported + * {@link DiscoverySessionCallback#onSessionTerminated()} is reported * back to the callback. * * @param enable If true the terminate callback will be called when the diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java index a0ec8093a3ab..39db1c715ae2 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java +++ b/wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java @@ -22,35 +22,35 @@ import android.util.Log; /** * A class representing a Aware subscribe session. Created when * {@link WifiAwareSession#subscribe(SubscribeConfig, - * WifiAwareDiscoverySessionCallback, android.os.Handler)} + * DiscoverySessionCallback, android.os.Handler)} * is called and a discovery session is created and returned in - * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(WifiAwareSubscribeDiscoverySession)}. - * See baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. + * {@link DiscoverySessionCallback#onSubscribeStarted(SubscribeDiscoverySession)}. + * See baseline functionality of all discovery sessions in {@link DiscoverySession}. * This object allows updating an existing/running subscribe discovery session using * {@link #updateSubscribe(SubscribeConfig)}. * * @hide PROPOSED_AWARE_API */ -public class WifiAwareSubscribeDiscoverySession extends WifiAwareDiscoveryBaseSession { - private static final String TAG = "WifiAwareSubsDiscSsn"; +public class SubscribeDiscoverySession extends DiscoverySession { + private static final String TAG = "SubscribeDiscSession"; /** * {@hide} */ - public WifiAwareSubscribeDiscoverySession(WifiAwareManager manager, int clientId, + public SubscribeDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) { super(manager, clientId, sessionId); } /** * Re-configure the currently active subscribe session. The - * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used + * {@link DiscoverySessionCallback} is not replaced - the same listener used * at creation is still used. The results of the configuration are returned using - * {@link WifiAwareDiscoverySessionCallback}: + * {@link DiscoverySessionCallback}: * <ul> - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration + * <li>{@link DiscoverySessionCallback#onSessionConfigUpdated()}: configuration * update succeeded. - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration + * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()}: configuration * update failed. The subscribe discovery session is still running using its previous * configuration (i.e. update failure does not terminate the session). * </ul> diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java index 029794dfa380..8c0a3a091579 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java @@ -58,14 +58,14 @@ import java.util.List; * The class provides access to: * <ul> * <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to - * {@link #attach(WifiAwareAttachCallback, Handler)}. + * {@link #attach(AttachCallback, Handler)}. * <li>Create discovery sessions (publish or subscribe sessions). Refer to - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)} and - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, Handler)}. + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)} and + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}. * <li>Create a Aware network specifier to be used with * {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)} * to set-up a Aware connection with a peer. Refer to - * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])} and + * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])} and * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}. * </ul> * <p> @@ -75,37 +75,37 @@ import java.util.List; * broadcast. Note that this broadcast is not sticky - you should register for it and then * check the above API to avoid a race condition. * <p> - * An application must use {@link #attach(WifiAwareAttachCallback, Handler)} to initialize a + * An application must use {@link #attach(AttachCallback, Handler)} to initialize a * Aware cluster - before making any other Aware operation. Aware cluster membership is a * device-wide operation - the API guarantees that the device is in a cluster or joins a * Aware cluster (or starts one if none can be found). Information about attach success (or - * failure) are returned in callbacks of {@link WifiAwareAttachCallback}. Proceed with Aware + * failure) are returned in callbacks of {@link AttachCallback}. Proceed with Aware * discovery or connection setup only after receiving confirmation that Aware attach - * succeeded - {@link WifiAwareAttachCallback#onAttached(WifiAwareSession)}. When an + * succeeded - {@link AttachCallback#onAttached(WifiAwareSession)}. When an * application is finished using Aware it <b>must</b> use the * {@link WifiAwareSession#destroy()} API to indicate to the Aware service that the device * may detach from the Aware cluster. The device will actually disable Aware once the last * application detaches. * <p> * Once a Aware attach is confirmed use the - * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)} + * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)} * or - * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, + * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, * Handler)} to create publish or subscribe Aware discovery sessions. Events are called on the - * provided callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the - * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)} + * provided callback object {@link DiscoverySessionCallback}. Specifically, the + * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)} * and - * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted( - * WifiAwareSubscribeDiscoverySession)} - * return {@link WifiAwarePublishDiscoverySession} and - * {@link WifiAwareSubscribeDiscoverySession} + * {@link DiscoverySessionCallback#onSubscribeStarted( + *SubscribeDiscoverySession)} + * return {@link PublishDiscoverySession} and + * {@link SubscribeDiscoverySession} * objects respectively on which additional session operations can be performed, e.g. updating - * the session {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} and - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can + * the session {@link PublishDiscoverySession#updatePublish(PublishConfig)} and + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can * also be used to send messages using the - * {@link WifiAwareDiscoveryBaseSession#sendMessage(PeerHandle, int, byte[])} APIs. When an + * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} APIs. When an * application is finished with a discovery session it <b>must</b> terminate it using the - * {@link WifiAwareDiscoveryBaseSession#destroy()} API. + * {@link DiscoverySession#destroy()} API. * <p> * Creating connections between Aware devices is managed by the standard * {@link ConnectivityManager#requestNetwork(NetworkRequest, @@ -116,7 +116,7 @@ import java.util.List; * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}. * <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} or - * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])}. + * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}. * </ul> * * @hide PROPOSED_AWARE_API @@ -226,7 +226,7 @@ public class WifiAwareManager { * Connection creation role is that of INITIATOR. Used to create a network specifier string * when requesting a Aware network. * - * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[]) + * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[]) * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[]) */ public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; @@ -235,7 +235,7 @@ public class WifiAwareManager { * Connection creation role is that of RESPONDER. Used to create a network specifier string * when requesting a Aware network. * - * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[]) + * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[]) * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[]) */ public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; @@ -307,7 +307,7 @@ public class WifiAwareManager { * @return An object specifying configuration limitations of Aware. * @hide PROPOSED_AWARE_API */ - public WifiAwareCharacteristics getCharacteristics() { + public Characteristics getCharacteristics() { try { return mService.getCharacteristics(); } catch (RemoteException e) { @@ -328,12 +328,12 @@ public class WifiAwareManager { * attachCallback}. * * @param attachCallback A callback for attach events, extended from - * {@link WifiAwareAttachCallback}. + * {@link AttachCallback}. * @param handler The Handler on whose thread to execute the callbacks of the {@code * attachCallback} object. If a null is provided then the application's main thread will be * used. */ - public void attach(@NonNull WifiAwareAttachCallback attachCallback, @Nullable Handler handler) { + public void attach(@NonNull AttachCallback attachCallback, @Nullable Handler handler) { attach(handler, null, attachCallback, null); } @@ -353,28 +353,28 @@ public class WifiAwareManager { * on startup and whenever it is updated (it is randomized at regular intervals for privacy). * The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} * permission to execute this attach request. Otherwise, use the - * {@link #attach(WifiAwareAttachCallback, Handler)} version. Note that aside from permission + * {@link #attach(AttachCallback, Handler)} version. Note that aside from permission * requirements this listener will wake up the host at regular intervals causing higher power * consumption, do not use it unless the information is necessary (e.g. for OOB discovery). * * @param attachCallback A callback for attach events, extended from - * {@link WifiAwareAttachCallback}. + * {@link AttachCallback}. * @param identityChangedListener A listener for changed identity, extended from - * {@link WifiAwareIdentityChangedListener}. + * {@link IdentityChangedListener}. * @param handler The Handler on whose thread to execute the callbacks of the {@code * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the * application's main thread will be used. */ - public void attach(@NonNull WifiAwareAttachCallback attachCallback, - @NonNull WifiAwareIdentityChangedListener identityChangedListener, + public void attach(@NonNull AttachCallback attachCallback, + @NonNull IdentityChangedListener identityChangedListener, @Nullable Handler handler) { attach(handler, null, attachCallback, identityChangedListener); } /** @hide */ public void attach(Handler handler, ConfigRequest configRequest, - WifiAwareAttachCallback attachCallback, - WifiAwareIdentityChangedListener identityChangedListener) { + AttachCallback attachCallback, + IdentityChangedListener identityChangedListener) { if (VDBG) { Log.v(TAG, "attach(): handler=" + handler + ", callback=" + attachCallback + ", configRequest=" + configRequest + ", identityChangedListener=" @@ -409,7 +409,7 @@ public class WifiAwareManager { /** @hide */ public void publish(int clientId, Looper looper, PublishConfig publishConfig, - WifiAwareDiscoverySessionCallback callback) { + DiscoverySessionCallback callback) { if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig); try { @@ -437,7 +437,7 @@ public class WifiAwareManager { /** @hide */ public void subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig, - WifiAwareDiscoverySessionCallback callback) { + DiscoverySessionCallback callback) { if (VDBG) { if (VDBG) { Log.v(TAG, @@ -672,14 +672,14 @@ public class WifiAwareManager { } /** - * Constructs a {@link WifiAwareAttachCallback} using the specified looper. + * Constructs a {@link AttachCallback} using the specified looper. * All callbacks will delivered on the thread of the specified looper. * * @param looper The looper on which to execute the callbacks. */ WifiAwareEventCallbackProxy(WifiAwareManager mgr, Looper looper, Binder binder, - final WifiAwareAttachCallback attachCallback, - final WifiAwareIdentityChangedListener identityChangedListener) { + final AttachCallback attachCallback, + final IdentityChangedListener identityChangedListener) { mAwareManager = new WeakReference<>(mgr); mLooper = looper; mBinder = binder; @@ -828,14 +828,14 @@ public class WifiAwareManager { private final WeakReference<WifiAwareManager> mAwareManager; private final boolean mIsPublish; - private final WifiAwareDiscoverySessionCallback mOriginalCallback; + private final DiscoverySessionCallback mOriginalCallback; private final int mClientId; private final Handler mHandler; - private WifiAwareDiscoveryBaseSession mSession; + private DiscoverySession mSession; WifiAwareDiscoverySessionCallbackProxy(WifiAwareManager mgr, Looper looper, - boolean isPublish, WifiAwareDiscoverySessionCallback originalCallback, + boolean isPublish, DiscoverySessionCallback originalCallback, int clientId) { mAwareManager = new WeakReference<>(mgr); mIsPublish = isPublish; @@ -1006,13 +1006,13 @@ public class WifiAwareManager { } if (mIsPublish) { - WifiAwarePublishDiscoverySession session = new WifiAwarePublishDiscoverySession(mgr, + PublishDiscoverySession session = new PublishDiscoverySession(mgr, mClientId, sessionId); mSession = session; mOriginalCallback.onPublishStarted(session); } else { - WifiAwareSubscribeDiscoverySession - session = new WifiAwareSubscribeDiscoverySession(mgr, mClientId, sessionId); + SubscribeDiscoverySession + session = new SubscribeDiscoverySession(mgr, mClientId, sessionId); mSession = session; mOriginalCallback.onSubscribeStarted(session); } @@ -1027,18 +1027,7 @@ public class WifiAwareManager { Log.w(TAG, "Proxy: onSessionTerminated called but mSession is null!?"); } mAwareManager.clear(); - mOriginalCallback.onSessionTerminated(reason); + mOriginalCallback.onSessionTerminated(); } } - - /** @hide PROPOSED_AWARE_API */ - public static class PeerHandle { - /** @hide */ - public PeerHandle(int peerId) { - this.peerId = peerId; - } - - /** @hide */ - public int peerId; - } } diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java index 005895a28043..e3ebe860f55f 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java @@ -65,7 +65,7 @@ public class WifiAwareSession { * session-wide destroy. * <p> * An application may re-attach after a destroy using - * {@link WifiAwareManager#attach(WifiAwareAttachCallback, Handler)} . + * {@link WifiAwareManager#attach(AttachCallback, Handler)} . */ public void destroy() { WifiAwareManager mgr = mMgr.get(); @@ -95,22 +95,22 @@ public class WifiAwareSession { /** * Issue a request to the Aware service to create a new Aware publish discovery session, using * the specified {@code publishConfig} configuration. The results of the publish operation - * are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}: + * are routed to the callbacks of {@link DiscoverySessionCallback}: * <ul> * <li> - * {@link WifiAwareDiscoverySessionCallback#onPublishStarted( - * WifiAwarePublishDiscoverySession)} + * {@link DiscoverySessionCallback#onPublishStarted( + *PublishDiscoverySession)} * is called when the publish session is created and provides a handle to the session. * Further operations on the publish session can be executed on that object. - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the + * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()} is called if the * publish operation failed. * </ul> * <p> * Other results of the publish session operations will also be routed to callbacks * on the {@code callback} object. The resulting publish session can be modified using - * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}. + * {@link PublishDiscoverySession#updatePublish(PublishConfig)}. * <p> - * An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to + * An application must use the {@link DiscoverySession#destroy()} to * terminate the publish discovery session once it isn't needed. This will free * resources as well terminate any on-air transmissions. * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} @@ -118,13 +118,13 @@ public class WifiAwareSession { * * @param publishConfig The {@link PublishConfig} specifying the * configuration of the requested publish session. - * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for + * @param callback A {@link DiscoverySessionCallback} derived object to be used for * session event callbacks. * @param handler The Handler on whose thread to execute the callbacks of the {@code * callback} object. If a null is provided then the application's main thread will be used. */ public void publish(@NonNull PublishConfig publishConfig, - @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) { + @NonNull DiscoverySessionCallback callback, @Nullable Handler handler) { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { Log.e(TAG, "publish: called post GC on WifiAwareManager"); @@ -141,22 +141,22 @@ public class WifiAwareSession { /** * Issue a request to the Aware service to create a new Aware subscribe discovery session, using * the specified {@code subscribeConfig} configuration. The results of the subscribe - * operation are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}: + * operation are routed to the callbacks of {@link DiscoverySessionCallback}: * <ul> * <li> - * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted( - * WifiAwareSubscribeDiscoverySession)} + * {@link DiscoverySessionCallback#onSubscribeStarted( + *SubscribeDiscoverySession)} * is called when the subscribe session is created and provides a handle to the session. * Further operations on the subscribe session can be executed on that object. - * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the + * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()} is called if the * subscribe operation failed. * </ul> * <p> * Other results of the subscribe session operations will also be routed to callbacks * on the {@code callback} object. The resulting subscribe session can be modified using - * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. + * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. * <p> - * An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to + * An application must use the {@link DiscoverySession#destroy()} to * terminate the subscribe discovery session once it isn't needed. This will free * resources as well terminate any on-air transmissions. * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} @@ -164,13 +164,13 @@ public class WifiAwareSession { * * @param subscribeConfig The {@link SubscribeConfig} specifying the * configuration of the requested subscribe session. - * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for + * @param callback A {@link DiscoverySessionCallback} derived object to be used for * session event callbacks. * @param handler The Handler on whose thread to execute the callbacks of the {@code * callback} object. If a null is provided then the application's main thread will be used. */ public void subscribe(@NonNull SubscribeConfig subscribeConfig, - @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) { + @NonNull DiscoverySessionCallback callback, @Nullable Handler handler) { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { Log.e(TAG, "publish: called post GC on WifiAwareManager"); @@ -193,7 +193,7 @@ public class WifiAwareSession { * This API is targeted for applications which can obtain the peer MAC address using OOB * (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer - * when using Aware discovery use the alternative network specifier method - - * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(WifiAwareManager.PeerHandle, + * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, * byte[])}. * * @param role The role of this device: diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java index 24c0127cb11b..a396d8775ab6 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -67,19 +67,19 @@ public class WifiAwareManagerTest { public Context mockContext; @Mock - public WifiAwareAttachCallback mockCallback; + public AttachCallback mockCallback; @Mock - public WifiAwareDiscoverySessionCallback mockSessionCallback; + public DiscoverySessionCallback mockSessionCallback; @Mock public IWifiAwareManager mockAwareService; @Mock - public WifiAwarePublishDiscoverySession mockPublishSession; + public PublishDiscoverySession mockPublishSession; @Mock - public WifiAwareSubscribeDiscoverySession mockSubscribeSession; + public SubscribeDiscoverySession mockSubscribeSession; @Mock public RttManager.RttListener mockRttListener; @@ -276,7 +276,7 @@ public class WifiAwareManagerTest { final int sessionId = 123; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final PublishConfig publishConfig = new PublishConfig.Builder().build(); - final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873); + final PeerHandle peerHandle = new PeerHandle(873); final String string1 = "hey from here..."; final byte[] matchFilter = { 1, 12, 2, 31, 32 }; final int messageId = 2123; @@ -290,10 +290,9 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor - .forClass(WifiAwarePublishDiscoverySession.class); - ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass( - WifiAwareManager.PeerHandle.class); + ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(PublishDiscoverySession.class); + ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class); ArgumentCaptor<List<byte[]>> matchFilterCaptor = ArgumentCaptor.forClass( (Class) List.class); @@ -377,7 +376,6 @@ public class WifiAwareManagerTest { final int sessionId = 123; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final PublishConfig publishConfig = new PublishConfig.Builder().build(); - final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE; InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, mockPublishSession); @@ -387,8 +385,8 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor - .forClass(WifiAwarePublishDiscoverySession.class); + ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(PublishDiscoverySession.class); // (1) connect successfully mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); @@ -404,10 +402,10 @@ public class WifiAwareManagerTest { inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), sessionProxyCallback.capture()); sessionProxyCallback.getValue().onSessionStarted(sessionId); - sessionProxyCallback.getValue().onSessionTerminated(reason); + sessionProxyCallback.getValue().onSessionTerminated(0); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture()); - inOrder.verify(mockSessionCallback).onSessionTerminated(reason); + inOrder.verify(mockSessionCallback).onSessionTerminated(); // (3) failure when trying to update: NOP publishSession.getValue().updatePublish(publishConfig); @@ -428,7 +426,7 @@ public class WifiAwareManagerTest { final int sessionId = 123; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873); + final PeerHandle peerHandle = new PeerHandle(873); final String string1 = "hey from here..."; final byte[] matchFilter = { 1, 12, 3, 31, 32 }; // bad data! final int messageId = 2123; @@ -442,10 +440,9 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor - .forClass(WifiAwareSubscribeDiscoverySession.class); - ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass( - WifiAwareManager.PeerHandle.class); + ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor + .forClass(SubscribeDiscoverySession.class); + ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class); // (0) connect + success mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); @@ -516,7 +513,6 @@ public class WifiAwareManagerTest { final int sessionId = 123; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); - final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE; InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, mockSubscribeSession); @@ -526,8 +522,8 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor - .forClass(WifiAwareSubscribeDiscoverySession.class); + ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor + .forClass(SubscribeDiscoverySession.class); // (1) connect successfully mDut.attach(mMockLooperHandler, configRequest, mockCallback, null); @@ -543,10 +539,10 @@ public class WifiAwareManagerTest { inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig), sessionProxyCallback.capture()); sessionProxyCallback.getValue().onSessionStarted(sessionId); - sessionProxyCallback.getValue().onSessionTerminated(reason); + sessionProxyCallback.getValue().onSessionTerminated(0); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture()); - inOrder.verify(mockSessionCallback).onSessionTerminated(reason); + inOrder.verify(mockSessionCallback).onSessionTerminated(); // (3) failure when trying to update: NOP subscribeSession.getValue().updateSubscribe(subscribeConfig); @@ -892,8 +888,8 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor - .forClass(WifiAwarePublishDiscoverySession.class); + ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(PublishDiscoverySession.class); ArgumentCaptor<RttManager.ParcelableRttParams> rttParamCaptor = ArgumentCaptor .forClass(RttManager.ParcelableRttParams.class); ArgumentCaptor<RttManager.RttResult[]> rttResultsCaptor = ArgumentCaptor @@ -953,7 +949,7 @@ public class WifiAwareManagerTest { public void testNetworkSpecifierWithClient() throws Exception { final int clientId = 4565; final int sessionId = 123; - final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(123412); + final PeerHandle peerHandle = new PeerHandle(123412); final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; final String token = "Some arbitrary token string - can really be anything"; final ConfigRequest configRequest = new ConfigRequest.Builder().build(); @@ -967,8 +963,8 @@ public class WifiAwareManagerTest { .forClass(IWifiAwareEventCallback.class); ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor .forClass(IWifiAwareDiscoverySessionCallback.class); - ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor - .forClass(WifiAwarePublishDiscoverySession.class); + ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor + .forClass(PublishDiscoverySession.class); InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService, mockPublishSession, mockRttListener); |