Merge "Fix LOCAL_SDK_VERSION of 3 multidex apks"
diff --git a/api/system-current.txt b/api/system-current.txt
index b2f2a3c..f597168 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40,6 +40,7 @@
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 @@
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 @@
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 @@
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 221d687..ec3371e 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -632,6 +632,7 @@
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 8f42467..857a361 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -509,10 +509,23 @@
* 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 @@
if (mCacheDir == null) {
mCacheDir = new File(getDataDir(), "cache");
}
- return ensurePrivateDirExists(mCacheDir);
+ return ensurePrivateCacheDirExists(mCacheDir);
}
}
@@ -591,7 +604,7 @@
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 353c640..1165fce 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -102,6 +102,27 @@
"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 @@
}
/**
+ * 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/BluetoothCodecConfig.aidl b/core/java/android/bluetooth/BluetoothCodecConfig.aidl
new file mode 100644
index 0000000..553e66e
--- /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 0000000..52cd2de
--- /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/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
index 0f0e050..f519776 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
@@ -45,9 +45,9 @@
* <code>false</code> otherwise.
*/
public void onAppStatusChanged(BluetoothDevice pluggedDevice,
- BluetoothHidDeviceAppConfiguration config, boolean registered) {
- Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + (pluggedDevice == null ?
- null : pluggedDevice.toString()) + " registered=" + registered);
+ BluetoothHidDeviceAppConfiguration config, boolean registered) {
+ Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + pluggedDevice + " registered="
+ + registered);
}
/**
@@ -60,13 +60,13 @@
* @param state Connection state as defined in {@link BluetoothProfile}.
*/
public void onConnectionStateChanged(BluetoothDevice device, int state) {
- Log.d(TAG, "onConnectionStateChanged: device=" + device.toString() + " state=" + 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(byte, byte, byte[])}.
+ * {@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
@@ -74,21 +74,22 @@
* @param bufferSize Requested buffer size, application shall respond with
* at least given number of bytes.
*/
- public void onGetReport(byte type, byte id, int bufferSize) {
- Log.d(TAG, "onGetReport: type=" + type + " id=" + id + " bufferSize=" + bufferSize);
+ 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()}.
+ * {@link BluetoothHidDevice#reportError(BluetoothDevice)}.
*
* @param type Report Type.
* @param id Report Id.
* @param data Report data.
*/
- public void onSetReport(byte type, byte id, byte[] data) {
- Log.d(TAG, "onSetReport: type=" + type + " id=" + id);
+ public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ Log.d(TAG, "onSetReport: device=" + device + " type=" + type + " id=" + id);
}
/**
@@ -99,8 +100,8 @@
*
* @param protocol Protocol Mode.
*/
- public void onSetProtocol(byte protocol) {
- Log.d(TAG, "onSetProtocol: protocol=" + protocol);
+ public void onSetProtocol(BluetoothDevice device, byte protocol) {
+ Log.d(TAG, "onSetProtocol: device=" + device + " protocol=" + protocol);
}
/**
@@ -111,16 +112,17 @@
* @param reportId Report Id.
* @param data Report data.
*/
- public void onIntrData(byte reportId, byte[] data) {
- Log.d(TAG, "onIntrData: reportId=" + reportId);
+ 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()} or request from remote side. After
- * this callback is received connection will be disconnected automatically.
+ * {@link BluetoothHidDevice#unplug(BluetoothDevice)} or request from remote
+ * side. After this callback is received connection will be disconnected
+ * automatically.
*/
- public void onVirtualCableUnplug() {
- Log.d(TAG, "onVirtualCableUnplug");
+ 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
index 129fe7e..68d105f 100644
--- a/core/java/android/bluetooth/BluetoothInputHost.java
+++ b/core/java/android/bluetooth/BluetoothInputHost.java
@@ -27,6 +27,7 @@
import android.util.Log;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -137,28 +138,28 @@
}
@Override
- public void onGetReport(byte type, byte id, int bufferSize) {
- mCallback.onGetReport(type, id, bufferSize);
+ public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
+ mCallback.onGetReport(device, type, id, bufferSize);
}
@Override
- public void onSetReport(byte type, byte id, byte[] data) {
- mCallback.onSetReport(type, id, data);
+ public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ mCallback.onSetReport(device, type, id, data);
}
@Override
- public void onSetProtocol(byte protocol) {
- mCallback.onSetProtocol(protocol);
+ public void onSetProtocol(BluetoothDevice device, byte protocol) {
+ mCallback.onSetProtocol(device, protocol);
}
@Override
- public void onIntrData(byte reportId, byte[] data) {
- mCallback.onIntrData(reportId, data);
+ public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) {
+ mCallback.onIntrData(device, reportId, data);
}
@Override
- public void onVirtualCableUnplug() {
- mCallback.onVirtualCableUnplug();
+ public void onVirtualCableUnplug(BluetoothDevice device) {
+ mCallback.onVirtualCableUnplug(device);
}
}
@@ -276,21 +277,59 @@
mServiceListener = null;
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public List<BluetoothDevice> getConnectedDevices() {
Log.v(TAG, "getConnectedDevices()");
- return null;
+
+ 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>();
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
- return null;
+
+ 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>();
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public int getConnectionState(BluetoothDevice device) {
- Log.v(TAG, "getConnectionState(): device=" + device.getAddress());
+ 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;
}
@@ -379,14 +418,12 @@
* @param data Report data, not including Report Id.
* @return
*/
- public boolean sendReport(int id, byte[] data) {
- Log.v(TAG, "sendReport(): id=" + id);
-
+ public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
if (mService != null) {
try {
- result = mService.sendReport(id, data);
+ result = mService.sendReport(device, id, data);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -399,21 +436,21 @@
/**
* Sends report to remote host as reply for GET_REPORT request from
- * {@link BluetoothHidDeviceCallback#onGetReport(byte, byte, int)}.
+ * {@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(byte type, byte id, byte[] data) {
- Log.v(TAG, "replyReport(): type=" + type + " id=" + id);
+ 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(type, id, data);
+ result = mService.replyReport(device, type, id, data);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -426,19 +463,19 @@
/**
* Sends error handshake message as reply for invalid SET_REPORT request
- * from {@link BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])}.
+ * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
*
* @param error Error to be sent for SET_REPORT via HANDSHAKE.
* @return
*/
- public boolean reportError(byte error) {
- Log.v(TAG, "reportError(): error = " + error);
+ 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(error);
+ result = mService.reportError(device, error);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -454,14 +491,14 @@
*
* @return
*/
- public boolean unplug() {
- Log.v(TAG, "unplug()");
+ public boolean unplug(BluetoothDevice device) {
+ Log.v(TAG, "unplug(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.unplug();
+ result = mService.unplug(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -478,14 +515,14 @@
*
* @return
*/
- public boolean connect() {
- Log.v(TAG, "connect()");
+ public boolean connect(BluetoothDevice device) {
+ Log.v(TAG, "connect(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.connect();
+ result = mService.connect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -501,14 +538,14 @@
*
* @return
*/
- public boolean disconnect() {
- Log.v(TAG, "disconnect()");
+ public boolean disconnect(BluetoothDevice device) {
+ Log.v(TAG, "disconnect(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.disconnect();
+ result = mService.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 26ff9e27..5b524eb 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 @@
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
index 1252876..a737198 100644
--- a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
@@ -23,9 +23,9 @@
interface IBluetoothHidDeviceCallback {
void onAppStatusChanged(in BluetoothDevice device, in BluetoothHidDeviceAppConfiguration config, boolean registered);
void onConnectionStateChanged(in BluetoothDevice device, in int state);
- void onGetReport(in byte type, in byte id, in int bufferSize);
- void onSetReport(in byte type, in byte id, in byte[] data);
- void onSetProtocol(in byte protocol);
- void onIntrData(in byte reportId, in byte[] data);
- void onVirtualCableUnplug();
+ 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
index b2c421c..6c4993f 100644
--- a/core/java/android/bluetooth/IBluetoothInputHost.aidl
+++ b/core/java/android/bluetooth/IBluetoothInputHost.aidl
@@ -28,10 +28,13 @@
in BluetoothHidDeviceAppSdpSettings sdp, in BluetoothHidDeviceAppQosSettings inQos,
in BluetoothHidDeviceAppQosSettings outQos, in IBluetoothHidDeviceCallback callback);
boolean unregisterApp(in BluetoothHidDeviceAppConfiguration config);
- boolean sendReport(in int id, in byte[] data);
- boolean replyReport(in byte type, in byte id, in byte[] data);
- boolean reportError(byte error);
- boolean unplug();
- boolean connect();
- boolean disconnect();
+ 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/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index 9464222..e1eaf00 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -87,9 +87,9 @@
{
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 e14facb1..d9ad74b 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -73,19 +73,27 @@
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 @@
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 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 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 FileDescriptor getFileDescriptor() {
return impl.getFileDescriptor();
- }
+ }
}
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index 0f0e9c4..d8f7821 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -235,29 +235,29 @@
* @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 4282ca7..ec0bb25d 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -231,13 +231,7 @@
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 a96f90d..d013f64 100644
--- a/core/java/android/net/RecommendationRequest.java
+++ b/core/java/android/net/RecommendationRequest.java
@@ -41,6 +41,7 @@
* 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 151239b..f6edee0 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -783,7 +783,7 @@
*/
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 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 481b2dc..e025494 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 @@
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 e617e0a..2f89ce6 100644
--- a/core/java/android/os/HwRemoteBinder.java
+++ b/core/java/android/os/HwRemoteBinder.java
@@ -32,12 +32,15 @@
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 f93bfd7..619f4dc 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -23,7 +23,8 @@
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 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 9cd1a42..d6688e3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -184,6 +184,11 @@
*/
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 b3f4453..535a05a 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -213,6 +213,15 @@
}
/**
+ * 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/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index e0d589a..2d6f443 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -24,6 +24,8 @@
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 @@
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;
+ 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 = getServiceName();
- if (serviceName == null) return;
+ // 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;
+ if (enabled && sZygote == null) {
+ SystemService.start(serviceName);
+ } else {
+ SystemService.stop(serviceName);
+ sZygote = null;
+ }
}
}
public static void onWebViewProviderChanged(PackageInfo packageInfo) {
- sPackage = packageInfo;
+ String serviceName;
+ synchronized (sLock) {
+ sPackage = packageInfo;
- // If multi-process is not enabled, then do not start the zygote service.
- if (!sMultiprocessEnabled) {
- return;
+ // If multi-process is not enabled, then do not start the zygote service.
+ if (!sMultiprocessEnabled) {
+ return;
+ }
+
+ serviceName = getServiceNameLocked();
+ sZygote = null;
+
+ // 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();
}
-
- final String serviceName = getServiceName();
-
- if (SystemService.isStopped(serviceName)) {
- SystemService.start(serviceName);
- } else if (sZygote != null) {
- SystemService.restart(serviceName);
- }
-
- try {
- SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
- } catch (TimeoutException e) {
- Log.e(LOGTAG, "Timed out waiting for " + serviceName);
- return;
- }
-
- connectToZygoteIfNeeded();
}
- private static String getServiceName() {
+ @GuardedBy("sLock")
+ private static String getServiceNameLocked() {
if (sPackage == null)
return null;
@@ -113,7 +149,8 @@
return WEBVIEW_ZYGOTE_SERVICE_32;
}
- private static void connectToZygoteIfNeeded() {
+ @GuardedBy("sLock")
+ private static void connectToZygoteIfNeededLocked() {
if (sZygote != null)
return;
@@ -122,7 +159,7 @@
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 8eb39e1..fbccfd5 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 @@
}
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 49760021..d30e6eb 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -457,6 +457,18 @@
}
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 @@
{"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_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 95e031b..20bb885 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 @@
jmethodID get;
} gArrayListMethods;
+static jclass gErrorClass;
+
static struct fields_t {
jfieldID contextID;
jmethodID onTransactID;
@@ -144,6 +148,22 @@
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 @@
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 @@
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 @@
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 @@
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 a10d807..b9d810a 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -49,7 +49,7 @@
} 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 @@
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 708bbba..f81de9b 100644
--- a/core/jni/android_os_HwParcel.h
+++ b/core/jni/android_os_HwParcel.h
@@ -67,7 +67,7 @@
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 0a7d84d..f2f8e52 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -347,7 +347,7 @@
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 60cf810..7cf11d4 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" />
@@ -1230,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 -->
<!-- ======================================= -->
@@ -2046,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 -->
<!-- ========================================= -->
@@ -2634,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 5bfff26..29020ba 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -169,6 +169,25 @@
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/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index 5d6b3a8..1f1939c 100755
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -294,7 +294,7 @@
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 33c1c3f..ce75bb49 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3278,6 +3278,20 @@
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 f597440..8a28255 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -678,6 +678,9 @@
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 c7931fc..9e5ac72 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -133,6 +133,8 @@
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 949acc0..d0f8b73b 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2336,10 +2336,7 @@
}
private void scanInternalSubtitleTracks() {
- if (mSubtitleController == null) {
- Log.d(TAG, "setSubtitleAnchor in MediaPlayer");
- setSubtitleAnchor();
- }
+ setSubtitleAnchor();
populateInbandTracks();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 5c8a6e2..a172e19 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 @@
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 adc59de..4f43eac 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -2029,6 +2029,11 @@
}
writer.flush();
+ if (args.length == 0) {
+ // Add arg to produce output
+ args = new String[1];
+ args[0] = "--print";
+ }
}
if (mBluetoothBinder == null) {
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 74ff41c..6296375 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -154,7 +154,8 @@
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/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5b02c79..bc03901 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 @@
* 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 7fe6c3e..5d619c1 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 @@
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 @@
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_A2DP_SINK_CONNECTION_STATE,
state,
- 0,
+ 0 /* arg2 unused */,
btDevice,
delay);
}
@@ -3163,7 +3164,7 @@
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_A2DP_SRC_CONNECTION_STATE,
state,
- 0,
+ 0 /* arg2 unused */,
btDevice,
0 /* delay */);
}
@@ -3809,8 +3810,8 @@
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 @@
(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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
}
}
+ 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/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 1f83d9e..605fa5d 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 @@
// 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 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 7ce5aa8..614230c 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 @@
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 @@
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 @@
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 69d27f2..9a9f81e 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.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 @@
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 0334254..811c996 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -233,6 +233,13 @@
*/
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 @@
// 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 @@
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;
}