Merge "Bump version for OtaDexoptService"
diff --git a/Android.mk b/Android.mk
index 2517f6b..147d2cf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -173,6 +173,8 @@
-knowntags ./frameworks/base/docs/knowntags.txt \
-knowntags ./libcore/known_oj_tags.txt \
-manifest ./frameworks/base/core/res/AndroidManifest.xml \
+ -hidePackage com.android.internal \
+ -hidePackage com.android.internal.util \
-hidePackage com.android.okhttp \
-hidePackage com.android.org.conscrypt \
-hidePackage com.android.server \
diff --git a/api/current.txt b/api/current.txt
index 62ba8a0..65dcae2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -39192,10 +39192,10 @@
method public void onStateChanged(android.telecom.Call, int);
method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
- field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
- field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
- field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
- field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5; // 0x5
+ field public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2; // 0x2
+ field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4; // 0x4
+ field public static final int HANDOVER_FAILURE_UNKNOWN = 5; // 0x5
+ field public static final int HANDOVER_FAILURE_USER_REJECTED = 3; // 0x3
}
public static class Call.Details {
@@ -39952,11 +39952,9 @@
package android.telephony {
public final class AccessNetworkConstants {
- ctor public AccessNetworkConstants();
}
public static final class AccessNetworkConstants.AccessNetworkType {
- ctor public AccessNetworkConstants.AccessNetworkType();
field public static final int CDMA2000 = 4; // 0x4
field public static final int EUTRAN = 3; // 0x3
field public static final int GERAN = 1; // 0x1
@@ -39966,7 +39964,6 @@
}
public static final class AccessNetworkConstants.EutranBand {
- ctor public AccessNetworkConstants.EutranBand();
field public static final int BAND_1 = 1; // 0x1
field public static final int BAND_10 = 10; // 0xa
field public static final int BAND_11 = 11; // 0xb
@@ -40018,7 +40015,6 @@
}
public static final class AccessNetworkConstants.GeranBand {
- ctor public AccessNetworkConstants.GeranBand();
field public static final int BAND_450 = 3; // 0x3
field public static final int BAND_480 = 4; // 0x4
field public static final int BAND_710 = 5; // 0x5
@@ -40036,7 +40032,6 @@
}
public static final class AccessNetworkConstants.UtranBand {
- ctor public AccessNetworkConstants.UtranBand();
field public static final int BAND_1 = 1; // 0x1
field public static final int BAND_10 = 10; // 0xa
field public static final int BAND_11 = 11; // 0xb
@@ -40473,7 +40468,8 @@
}
public class NetworkScan {
- method public void stop() throws android.os.RemoteException;
+ method public deprecated void stop() throws android.os.RemoteException;
+ method public void stopScan();
field public static final int ERROR_INTERRUPTED = 10002; // 0x2712
field public static final int ERROR_INVALID_SCAN = 2; // 0x2
field public static final int ERROR_INVALID_SCANID = 10001; // 0x2711
@@ -40897,7 +40893,8 @@
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
- method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
+ method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
+ method public deprecated android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(java.lang.String);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
diff --git a/api/system-current.txt b/api/system-current.txt
index d66c153..2f1b140 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4111,7 +4111,6 @@
package android.telephony {
public static final class AccessNetworkConstants.TransportType {
- ctor public AccessNetworkConstants.TransportType();
field public static final int WLAN = 2; // 0x2
field public static final int WWAN = 1; // 0x1
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 4be01d0..2fc8c68 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.IntDef;
-import android.annotation.SystemApi;
import android.net.ConnectivityManager.NetworkCallback;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 3b6df5d..0789afd 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -196,9 +196,14 @@
*/
public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy
+ /**
+ * @hide
+ */
+ public static final int DETECT_EXPLICIT_GC = 0x40; // for ThreadPolicy
+
private static final int ALL_THREAD_DETECT_BITS =
DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM |
- DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO;
+ DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO | DETECT_EXPLICIT_GC;
// Byte 2: Process-policy
@@ -557,6 +562,27 @@
}
/**
+ * Detect explicit GC requests, i.e. calls to Runtime.gc().
+ *
+ * @hide
+ */
+ public Builder detectExplicitGc() {
+ // TODO(b/3400644): Un-hide this for next API update
+ // TODO(b/3400644): Call this from detectAll in next API update
+ return enable(DETECT_EXPLICIT_GC);
+ }
+
+ /**
+ * Disable detection of explicit GC requests, i.e. calls to Runtime.gc().
+ *
+ * @hide
+ */
+ public Builder permitExplicitGc() {
+ // TODO(b/3400644): Un-hide this for next API update
+ return disable(DETECT_EXPLICIT_GC);
+ }
+
+ /**
* Show an annoying dialog to the developer on detected
* violations, rate-limited to be only a little annoying.
*/
@@ -1094,6 +1120,15 @@
}
/**
+ * @hide
+ */
+ private static class StrictModeExplicitGcViolation extends StrictModeViolation {
+ StrictModeExplicitGcViolation(int policyMask) {
+ super(policyMask, DETECT_EXPLICIT_GC, null);
+ }
+ }
+
+ /**
* Returns the bitmask of the current thread's policy.
*
* @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
@@ -1414,7 +1449,7 @@
startHandlingViolationException(e);
}
- // Part of BlockGuard.Policy; just part of StrictMode:
+ // Part of BlockGuard.Policy interface:
public void onUnbufferedIO() {
if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
return;
@@ -1457,6 +1492,20 @@
startHandlingViolationException(e);
}
+ // Part of BlockGuard.Policy interface:
+ public void onExplicitGc() {
+ if ((mPolicyMask & DETECT_EXPLICIT_GC) == 0) {
+ return;
+ }
+ if (tooManyViolationsThisLoop()) {
+ return;
+ }
+ BlockGuard.BlockGuardPolicyException e =
+ new StrictModeExplicitGcViolation(mPolicyMask);
+ e.fillInStackTrace();
+ startHandlingViolationException(e);
+ }
+
public void setPolicyMask(int policyMask) {
mPolicyMask = policyMask;
}
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
index cb4f104..4bbee61 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ b/core/java/android/service/euicc/EuiccProfileInfo.java
@@ -441,7 +441,7 @@
+ ", state="
+ mState
+ ", CarrierIdentifier="
- + mCarrierIdentifier.toString()
+ + mCarrierIdentifier
+ ", policyRules="
+ mPolicyRules
+ ", accessRules="
diff --git a/core/tests/BroadcastRadioTests/Android.mk b/core/tests/BroadcastRadioTests/Android.mk
index c409e3a..69bae86 100644
--- a/core/tests/BroadcastRadioTests/Android.mk
+++ b/core/tests/BroadcastRadioTests/Android.mk
@@ -23,6 +23,7 @@
LOCAL_MODULE_TAGS := tests
# TODO(b/13282254): uncomment when b/13282254 is fixed
# LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test testng
diff --git a/core/tests/overlaytests/OverlayTest/Android.mk b/core/tests/overlaytests/OverlayTest/Android.mk
index 964348f..8f4b829 100644
--- a/core/tests/overlaytests/OverlayTest/Android.mk
+++ b/core/tests/overlaytests/OverlayTest/Android.mk
@@ -5,6 +5,8 @@
LOCAL_PACKAGE_NAME := OverlayTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
LOCAL_DEX_PREOPT := false
LOCAL_JAVA_LIBRARIES += legacy-test
diff --git a/packages/CaptivePortalLogin/Android.mk b/packages/CaptivePortalLogin/Android.mk
index 576debc..e6e0ad3 100644
--- a/packages/CaptivePortalLogin/Android.mk
+++ b/packages/CaptivePortalLogin/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CaptivePortalLogin
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
diff --git a/packages/CarrierDefaultApp/Android.mk b/packages/CarrierDefaultApp/Android.mk
index 82be132..df88afd 100644
--- a/packages/CarrierDefaultApp/Android.mk
+++ b/packages/CarrierDefaultApp/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CarrierDefaultApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.mk b/packages/CarrierDefaultApp/tests/unit/Android.mk
index 63bd0b1..a95ccfe 100644
--- a/packages/CarrierDefaultApp/tests/unit/Android.mk
+++ b/packages/CarrierDefaultApp/tests/unit/Android.mk
@@ -27,6 +27,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CarrierDefaultAppUnitTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_INSTRUMENTATION_FOR := CarrierDefaultApp
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 3cda9c9..784c714 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -444,6 +444,7 @@
private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice,
int bluetoothProfile) {
+ mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile);
synchronized (mCallbacks) {
for (BluetoothCallback callback : mCallbacks) {
callback.onActiveDeviceChanged(activeDevice, bluetoothProfile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index e1ebbc4..f6ec6a8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -27,6 +27,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.bluetooth.BluetoothAdapter;
+import android.support.annotation.VisibleForTesting;
import com.android.settingslib.R;
@@ -461,12 +462,12 @@
}
/**
- * Set the device status as active or non-active per Bluetooth profile.
+ * Update the device status as active or non-active per Bluetooth profile.
*
* @param isActive true if the device is active
* @param bluetoothProfile the Bluetooth profile
*/
- public void setActiveDevice(boolean isActive, int bluetoothProfile) {
+ public void onActiveDeviceChanged(boolean isActive, int bluetoothProfile) {
boolean changed = false;
switch (bluetoothProfile) {
case BluetoothProfile.A2DP:
@@ -478,7 +479,7 @@
mIsActiveDeviceHeadset = isActive;
break;
default:
- Log.w(TAG, "setActiveDevice: unknown profile " + bluetoothProfile +
+ Log.w(TAG, "onActiveDeviceChanged: unknown profile " + bluetoothProfile +
" isActive " + isActive);
break;
}
@@ -487,6 +488,26 @@
}
}
+ /**
+ * Get the device status as active or non-active per Bluetooth profile.
+ *
+ * @param bluetoothProfile the Bluetooth profile
+ * @return true if the device is active
+ */
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ public boolean isActiveDevice(int bluetoothProfile) {
+ switch (bluetoothProfile) {
+ case BluetoothProfile.A2DP:
+ return mIsActiveDeviceA2dp;
+ case BluetoothProfile.HEADSET:
+ return mIsActiveDeviceHeadset;
+ default:
+ Log.w(TAG, "getActiveDevice: unknown profile " + bluetoothProfile);
+ break;
+ }
+ return false;
+ }
+
void setRssi(short rssi) {
if (mRssi != rssi) {
mRssi = rssi;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index c3ff617..a8e0039 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Objects;
/**
* CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
@@ -167,6 +168,15 @@
}
}
}
+
+ public synchronized void onActiveDeviceChanged(CachedBluetoothDevice activeDevice,
+ int bluetoothProfile) {
+ for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+ boolean isActive = Objects.equals(cachedDevice, activeDevice);
+ cachedDevice.onActiveDeviceChanged(isActive, bluetoothProfile);
+ }
+ }
+
private void log(String msg) {
if (DEBUG) {
Log.d(TAG, msg);
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index 7ace048..5bd9e4c 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -25,6 +25,7 @@
LOCAL_JACK_FLAGS := --multi-dex native
LOCAL_PACKAGE_NAME := SettingsLibTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_STATIC_JAVA_LIBRARIES := \
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index 55b635e..bc28863 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -21,6 +21,7 @@
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := SettingsLibShell
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_MODULE_TAGS := optional
LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
new file mode 100644
index 0000000..d6b2006
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2018 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 com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.Collection;
+
+@RunWith(RobolectricTestRunner.class)
+public class CachedBluetoothDeviceManagerTest {
+ private final static String DEVICE_NAME_1 = "TestName_1";
+ private final static String DEVICE_NAME_2 = "TestName_2";
+ private final static String DEVICE_ALIAS_1 = "TestAlias_1";
+ private final static String DEVICE_ALIAS_2 = "TestAlias_2";
+ private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
+ private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
+ private final BluetoothClass DEVICE_CLASS_1 =
+ new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+ private final BluetoothClass DEVICE_CLASS_2 =
+ new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+ @Mock
+ private LocalBluetoothAdapter mLocalAdapter;
+ @Mock
+ private LocalBluetoothProfileManager mLocalProfileManager;
+ @Mock
+ private LocalBluetoothManager mLocalBluetoothManager;
+ @Mock
+ private BluetoothEventManager mBluetoothEventManager;
+ @Mock
+ private HeadsetProfile mHfpProfile;
+ @Mock
+ private A2dpProfile mA2dpProfile;
+ @Mock
+ private PanProfile mPanProfile;
+ @Mock
+ private BluetoothDevice mDevice1;
+ @Mock
+ private BluetoothDevice mDevice2;
+ private CachedBluetoothDeviceManager mCachedDeviceManager;
+ private Context mContext;
+ private String[] mActiveDeviceStringsArray;
+ private String mActiveDeviceStringNone;
+ private String mActiveDeviceStringAll;
+ private String mActiveDeviceStringMedia;
+ private String mActiveDeviceStringPhone;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
+ when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
+ when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
+ when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
+ when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
+ when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
+ when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1);
+ when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
+
+ when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
+ when(mLocalAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
+ when(mHfpProfile.isProfileReady()).thenReturn(true);
+ when(mA2dpProfile.isProfileReady()).thenReturn(true);
+ when(mPanProfile.isProfileReady()).thenReturn(true);
+ mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
+ }
+
+ /**
+ * Test to verify addDevice().
+ */
+ @Test
+ public void testAddDevice_validCachedDevices_devicesAdded() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+
+ Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+ assertThat(devices).contains(cachedDevice1);
+ assertThat(devices).contains(cachedDevice2);
+
+ assertThat(mCachedDeviceManager.findDevice(mDevice1)).isEqualTo(cachedDevice1);
+ assertThat(mCachedDeviceManager.findDevice(mDevice2)).isEqualTo(cachedDevice2);
+ }
+
+ /**
+ * Test to verify getName().
+ */
+ @Test
+ public void testGetName_validCachedDevice_nameFound() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ assertThat(mCachedDeviceManager.getName(mDevice1)).isEqualTo(DEVICE_ALIAS_1);
+ }
+
+ /**
+ * Test to verify onDeviceNameUpdated().
+ */
+ @Test
+ public void testOnDeviceNameUpdated_validName_nameUpdated() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1);
+
+ final String newAliasName = "NewAliasName";
+ when(mDevice1.getAliasName()).thenReturn(newAliasName);
+ mCachedDeviceManager.onDeviceNameUpdated(mDevice1);
+ assertThat(cachedDevice1.getName()).isEqualTo(newAliasName);
+ }
+
+ /**
+ * Test to verify clearNonBondedDevices().
+ */
+ @Test
+ public void testClearNonBondedDevices_bondedAndNonBondedDevices_nonBondedDevicesCleared() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
+ mCachedDeviceManager.clearNonBondedDevices();
+ Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+ assertThat(devices).contains(cachedDevice1);
+ assertThat(devices).contains(cachedDevice2);
+
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+ mCachedDeviceManager.clearNonBondedDevices();
+ devices = mCachedDeviceManager.getCachedDevicesCopy();
+ assertThat(devices).contains(cachedDevice1);
+ assertThat(devices).doesNotContain(cachedDevice2);
+
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+ mCachedDeviceManager.clearNonBondedDevices();
+ devices = mCachedDeviceManager.getCachedDevicesCopy();
+ assertThat(devices).doesNotContain(cachedDevice1);
+ assertThat(devices).doesNotContain(cachedDevice2);
+ }
+
+ /**
+ * Test to verify onBtClassChanged().
+ */
+ @Test
+ public void testOnBtClassChanged_validBtClass_classChanged() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1);
+
+ final BluetoothClass newBluetoothClass = DEVICE_CLASS_2;
+ when(mDevice1.getBluetoothClass()).thenReturn(newBluetoothClass);
+ mCachedDeviceManager.onBtClassChanged(mDevice1);
+ assertThat(cachedDevice1.getBtClass()).isEqualTo(newBluetoothClass);
+ }
+
+ /**
+ * Test to verify onDeviceDisappeared().
+ */
+ @Test
+ public void testOnDeviceDisappeared_deviceBondedUnbonded_unbondedDeviceDisappeared() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isFalse();
+
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+ assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isTrue();
+ }
+
+ /**
+ * Test to verify onActiveDeviceChanged().
+ */
+ @Test
+ public void testOnActiveDeviceChanged_connectedDevices_activeDeviceChanged() {
+ CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice1);
+ assertThat(cachedDevice1).isNotNull();
+ CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+ mLocalProfileManager, mDevice2);
+ assertThat(cachedDevice2).isNotNull();
+
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+
+ // Connect both devices for A2DP and HFP
+ cachedDevice1.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ cachedDevice2.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ cachedDevice1.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ cachedDevice2.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+
+ // Verify that both devices are connected and none is Active
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+
+ // The first device is active for A2DP, the second device is active for HFP
+ mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.A2DP);
+ mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET);
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+ // The first device is active for A2DP and HFP
+ mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.HEADSET);
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+
+ // The second device is active for A2DP and HFP
+ mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.A2DP);
+ mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET);
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+ // No active device for A2DP
+ mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.A2DP);
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+ // No active device for HFP
+ mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.HEADSET);
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+ assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 1481161..2c91d5a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -152,7 +152,7 @@
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
// Set device as Active for A2DP and test connection state summary
- mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)");
// Test with battery level
@@ -168,7 +168,7 @@
mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
// Set A2DP profile to be connected, Active and test connection state summary
mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
- mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)");
// Set A2DP profile to be disconnected and test connection state summary
@@ -184,7 +184,7 @@
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
// Set device as Active for HFP and test connection state summary
- mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)");
// Test with battery level
@@ -200,7 +200,7 @@
mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
// Set HFP profile to be connected, Active and test connection state summary
mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
- mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)");
// Set HFP profile to be disconnected and test connection state summary
@@ -217,8 +217,8 @@
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
// Set device as Active for A2DP and HFP and test connection state summary
- mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
- mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active");
// Test with battery level
@@ -227,16 +227,16 @@
"Connected, battery 10%, active");
// Disconnect A2DP only and test connection state summary
- mCachedDevice.setActiveDevice(false, BluetoothProfile.A2DP);
+ mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
"Connected (no media), battery 10%, active(phone)");
// Disconnect HFP only and test connection state summary
- mCachedDevice.setActiveDevice(false, BluetoothProfile.HEADSET);
+ mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
- mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
"Connected (no phone), battery 10%, active(media)");
@@ -245,8 +245,8 @@
// Set A2DP and HFP profiles to be connected, Active and test connection state summary
mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
- mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
- mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active");
// Set A2DP and HFP profiles to be disconnected and test connection state summary
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 2fd7e87..2bfd3a5 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -48,6 +48,7 @@
LOCAL_JAVA_LIBRARIES += android.car
LOCAL_PACKAGE_NAME := SystemUI
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/SystemUI/plugin/Android.mk b/packages/SystemUI/plugin/Android.mk
index e22dddb..8634684 100644
--- a/packages/SystemUI/plugin/Android.mk
+++ b/packages/SystemUI/plugin/Android.mk
@@ -32,6 +32,7 @@
# Dummy to generate .toc files.
LOCAL_PACKAGE_NAME := PluginDummyLib
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := SystemUIPluginLib
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 27c16d5..fce71b9 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -26,6 +26,7 @@
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
LOCAL_PACKAGE_NAME := SystemUITests
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 900e188..d1abd63 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10206,6 +10206,17 @@
mPackageUsage.writeNow(mPackages);
mCompilerStats.writeNow();
mDexManager.writePackageDexUsageNow();
+
+ // This is the last chance to write out pending restriction settings
+ synchronized (mPackages) {
+ if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
+ mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+ for (int userId : mDirtyUsers) {
+ mSettings.writePackageRestrictionsLPr(userId);
+ }
+ mDirtyUsers.clear();
+ }
+ }
}
@Override
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a79f2c9..73243d2 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -879,42 +879,76 @@
/**
* @hide
*/
- @IntDef({HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_DEST_NOT_SUPPORTED,
- HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED,
- HANDOVER_FAILURE_ONGOING_EMERG_CALL})
+ @IntDef(prefix = { "HANDOVER_" },
+ value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
+ HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERG_CALL,
+ HANDOVER_FAILURE_UNKNOWN})
@Retention(RetentionPolicy.SOURCE)
public @interface HandoverFailureErrors {}
/**
* Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
- * to handover the call rejects handover.
+ * to handover the call to rejects the handover request.
+ * <p>
+ * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
+ * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
+ * {@code null} {@link Connection} from
+ * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+ * ConnectionRequest)}.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
/**
- * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there is
- * an error associated with unsupported handover.
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+ * is initiated but the source or destination app does not support handover.
+ * <p>
+ * Will be returned when a handover is requested via
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
+ * {@link PhoneAccountHandle} does not declare
+ * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is
+ * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
+ * {@link Details#getAccountHandle()}) does not declare
+ * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
- public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2;
+ public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
/**
- * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
- * are some permission errors associated with APIs doing handover.
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
+ * user rejects the handover request.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
- public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3;
-
- /**
- * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when user
- * rejects handover.
- */
- public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4;
+ public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
/**
* Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
* is ongoing emergency call.
+ * <p>
+ * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
+ * called on an emergency call, or if any other call is an emergency call.
+ * <p>
+ * Handovers are not permitted while there are ongoing emergency calls.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
*/
- public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5;
+ public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4;
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+ * fails for an unknown reason.
+ * <p>
+ * For more information on call handovers, see
+ * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
+ */
+ public static final int HANDOVER_FAILURE_UNKNOWN = 5;
/**
* Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
@@ -1055,6 +1089,10 @@
/**
* Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
* has completed successfully.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ *
* @param call The call which had initiated handover.
*/
public void onHandoverComplete(Call call) {}
@@ -1062,8 +1100,12 @@
/**
* Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
* has failed.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ *
* @param call The call which had initiated handover.
- * @param failureReason Error reason for failure
+ * @param failureReason Error reason for failure.
*/
public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
}
@@ -1260,7 +1302,7 @@
* Instructs this {@link #STATE_RINGING} {@code Call} to answer.
* @param videoState The video state in which to answer the call.
*/
- public void answer(int videoState) {
+ public void answer(@VideoProfile.VideoState int videoState) {
mInCallAdapter.answerCall(mTelecomCallId, videoState);
}
@@ -1474,16 +1516,65 @@
* by {@code toHandle}. The videoState specified indicates the desired video state after the
* handover.
* <p>
- * A handover request is initiated by the user from one app to indicate a desire
- * to handover a call to another.
+ * A call handover is the process where an ongoing call is transferred from one app (i.e.
+ * {@link ConnectionService} to another app. The user could, for example, choose to continue a
+ * mobile network call in a video calling app. The mobile network call via the Telephony stack
+ * is referred to as the source of the handover, and the video calling app is referred to as the
+ * destination.
+ * <p>
+ * When considering a handover scenario the device this method is called on is considered the
+ * <em>initiating</em> device (since the user initiates the handover from this device), and the
+ * other device is considered the <em>receiving</em> device.
+ * <p>
+ * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
+ * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
+ * and invoke
+ * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+ * ConnectionRequest)} to inform the destination app that a request has been made to handover a
+ * call to it. The app returns an instance of {@link Connection} to represent the handover call
+ * At this point the app should display UI to indicate to the user that a call
+ * handover is in process.
+ * <p>
+ * The destination app is responsible for communicating the handover request from the
+ * <em>initiating</em> device to the <em>receiving</em> device.
+ * <p>
+ * When the app on the <em>receiving</em> device receives the handover request, it calls
+ * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
+ * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point
+ * the destination app on the <em>receiving</em> device should show UI to allow the user to
+ * choose whether they want to continue their call in the destination app.
+ * <p>
+ * When the destination app on the <em>receiving</em> device calls
+ * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
+ * {@link ConnectionService} and call
+ * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
+ * ConnectionRequest)} to inform it of the handover request. The app returns an instance of
+ * {@link Connection} to represent the handover call.
+ * <p>
+ * If the user of the <em>receiving</em> device accepts the handover, the app calls
+ * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
+ * original call. If the user rejects the handover, the app calls
+ * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
+ * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
+ * <p>
+ * Telecom will only allow handovers from {@link PhoneAccount}s which declare
+ * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount}
+ * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
+ * <p>
+ * Errors in the handover process are reported to the {@link InCallService} via
+ * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to
+ * the involved {@link ConnectionService}s via
+ * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
*
* @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
* this call to.
- * @param videoState Indicates the video state desired after the handover.
+ * @param videoState Indicates the video state desired after the handover (see the
+ * {@code STATE_*} constants defined in {@link VideoProfile}).
* @param extras Bundle containing extra information to be passed to the
* {@link ConnectionService}
*/
- public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
+ public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
+ Bundle extras) {
mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 593e12b..2fdbc71 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -2218,12 +2218,50 @@
}
/**
- * Called by Telecom on the initiating side of the handover to create an instance of a
- * handover connection.
+ * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+ * outgoing handover {@link Connection}.
+ * <p>
+ * A call handover is the process where an ongoing call is transferred from one app (i.e.
+ * {@link ConnectionService} to another app. The user could, for example, choose to continue a
+ * mobile network call in a video calling app. The mobile network call via the Telephony stack
+ * is referred to as the source of the handover, and the video calling app is referred to as the
+ * destination.
+ * <p>
+ * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+ * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+ * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+ * device.
+ * <p>
+ * This method is called on the destination {@link ConnectionService} on <em>initiating</em>
+ * device when the user initiates a handover request from one app to another. The user request
+ * originates in the {@link InCallService} via
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ * <p>
+ * Implementations of this method should return an instance of {@link Connection} which
+ * represents the handover. If your app does not wish to accept a handover to it at this time,
+ * you can return {@code null}. The code below shows an example of how this is done.
+ * <pre>
+ * {@code
+ * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+ * fromPhoneAccountHandle, ConnectionRequest request) {
+ * if (!isHandoverAvailable()) {
+ * return null;
+ * }
+ * MyConnection connection = new MyConnection();
+ * connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+ * connection.setVideoState(request.getVideoState());
+ * return connection;
+ * }
+ * }
+ * </pre>
+ *
* @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
* ConnectionService which needs to handover the call.
- * @param request Details about the call which needs to be handover.
- * @return Connection object corresponding to the handover call.
+ * @param request Details about the call to handover.
+ * @return {@link Connection} instance corresponding to the handover call.
*/
public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
ConnectionRequest request) {
@@ -2231,12 +2269,46 @@
}
/**
- * Called by Telecom on the receiving side of the handover to request the
- * {@link ConnectionService} to create an instance of a handover connection.
+ * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+ * incoming handover {@link Connection}.
+ * <p>
+ * A call handover is the process where an ongoing call is transferred from one app (i.e.
+ * {@link ConnectionService} to another app. The user could, for example, choose to continue a
+ * mobile network call in a video calling app. The mobile network call via the Telephony stack
+ * is referred to as the source of the handover, and the video calling app is referred to as the
+ * destination.
+ * <p>
+ * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+ * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+ * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+ * device.
+ * <p>
+ * This method is called on the destination app on the <em>receiving</em> device when the
+ * destination app calls {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to
+ * accept an incoming handover from the <em>initiating</em> device.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ * <p>
+ * Implementations of this method should return an instance of {@link Connection} which
+ * represents the handover. The code below shows an example of how this is done.
+ * <pre>
+ * {@code
+ * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+ * fromPhoneAccountHandle, ConnectionRequest request) {
+ * // Given that your app requested to accept the handover, you should not return null here.
+ * MyConnection connection = new MyConnection();
+ * connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+ * connection.setVideoState(request.getVideoState());
+ * return connection;
+ * }
+ * }
+ * </pre>
+ *
* @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
* ConnectionService which needs to handover the call.
* @param request Details about the call which needs to be handover.
- * @return {@link Connection} object corresponding to the handover call.
+ * @return {@link Connection} instance corresponding to the handover call.
*/
public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
ConnectionRequest request) {
@@ -2246,11 +2318,15 @@
/**
* Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
* invocation which failed.
- * @param request Details about the call which needs to be handover.
- * @param error Reason for handover failure as defined in
- * {@link android.telecom.Call.Callback#HANDOVER_FAILURE_DEST_INVALID_PERM}
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}
+ *
+ * @param request Details about the call which failed to handover.
+ * @param error Reason for handover failure. Will be one of the
*/
- public void onHandoverFailed(ConnectionRequest request, int error) {
+ public void onHandoverFailed(ConnectionRequest request,
+ @Call.Callback.HandoverFailureErrors int error) {
return;
}
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
index 4fc3385..2bda648 100644
--- a/telecomm/java/android/telecom/Logging/EventManager.java
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -24,21 +24,20 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Date;
import java.util.HashMap;
import java.util.IllegalFormatException;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.TimeZone;
import java.util.concurrent.LinkedBlockingQueue;
-import java.util.stream.Collectors;
/**
* A utility class that provides the ability to define Events that a subsystem deems important, and
@@ -53,7 +52,8 @@
public static final String TAG = "Logging.Events";
@VisibleForTesting
public static final int DEFAULT_EVENTS_TO_CACHE = 10; // Arbitrarily chosen.
- private final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
+ public static final DateTimeFormatter DATE_TIME_FORMATTER =
+ DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
public interface Loggable {
/**
@@ -131,11 +131,17 @@
public String sessionId;
public long time;
public Object data;
+ // String storing the date for display. This will be computed at the time/timezone when
+ // the event is recorded.
+ public final String timestampString;
public Event(String eventId, String sessionId, long time, Object data) {
this.eventId = eventId;
this.sessionId = sessionId;
this.time = time;
+ timestampString =
+ ZonedDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault())
+ .format(DATE_TIME_FORMATTER);
this.data = data;
}
}
@@ -228,7 +234,7 @@
pw.increaseIndent();
for (Event event : mEvents) {
- pw.print(sDateFormat.format(new Date(event.time)));
+ pw.print(event.timestampString);
pw.print(" - ");
pw.print(event.eventId);
if (event.data != null) {
@@ -269,7 +275,6 @@
public EventManager(@NonNull SessionManager.ISessionIdQueryHandler l) {
mSessionIdHandler = l;
- sDateFormat.setTimeZone(TimeZone.getDefault());
}
public void event(Loggable recordEntry, String event, Object data) {
@@ -329,15 +334,15 @@
}
}
- // Sort by event time.
- Comparator<Pair<Loggable, Event>> byEventTime = (e1, e2) -> {
- return Long.compare(e1.second.time, e2.second.time);
- };
+ // Sort by event time. This might result in out-of-order seeming events if the timezone
+ // changes somewhere in the middle.
+ Comparator<Pair<Loggable, Event>> byEventTime =
+ Comparator.comparingLong(e -> e.second.time);
events.sort(byEventTime);
pw.increaseIndent();
for (Pair<Loggable, Event> event : events) {
- pw.print(sDateFormat.format(new Date(event.second.time)));
+ pw.print(event.second.timestampString);
pw.print(",");
pw.print(event.first.getId());
pw.print(",");
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 59ce590..bb4b483 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -93,6 +93,10 @@
// failure on the providing end, so immediately mark it destroyed
connection.setDestroyed();
}
+ connection.setStatusHints(parcel.getStatusHints());
+ connection.setIsVoipAudioMode(parcel.getIsVoipAudioMode());
+ connection.setRingbackRequested(parcel.isRingbackRequested());
+ connection.putExtras(parcel.getExtras());
}
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index c848f77..4b1f0ad 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1786,8 +1786,25 @@
}
/**
- * Called from the recipient side of a handover to indicate a desire to accept the handover
- * of an ongoing call to another {@link ConnectionService} identified by
+ * Called by an app to indicate that it wishes to accept the handover of an ongoing call to a
+ * {@link PhoneAccountHandle} it defines.
+ * <p>
+ * A call handover is the process where an ongoing call is transferred from one app (i.e.
+ * {@link ConnectionService} to another app. The user could, for example, choose to continue a
+ * mobile network call in a video calling app. The mobile network call via the Telephony stack
+ * is referred to as the source of the handover, and the video calling app is referred to as the
+ * destination.
+ * <p>
+ * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+ * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+ * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+ * device.
+ * <p>
+ * For a full discussion of the handover process and the APIs involved, see
+ * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+ * <p>
+ * This method is called from the <em>receiving</em> side of a handover to indicate a desire to
+ * accept the handover of an ongoing call to another {@link ConnectionService} identified by
* {@link PhoneAccountHandle} destAcct. For managed {@link ConnectionService}s, the specified
* {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
* the user must have enabled the corresponding {@link PhoneAccount}. This can be checked using
@@ -1811,7 +1828,8 @@
* @param videoState Video state after the handover.
* @param destAcct The {@link PhoneAccountHandle} registered to the calling package.
*/
- public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
+ public void acceptHandover(Uri srcAddr, @VideoProfile.VideoState int videoState,
+ PhoneAccountHandle destAcct) {
try {
if (isServiceConnected()) {
getTelecomService().acceptHandover(srcAddr, videoState, destAcct);
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index e0e3a08..90ed36f 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -62,6 +62,7 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef(
flag = true,
+ prefix = { "STATE_" },
value = {STATE_AUDIO_ONLY, STATE_TX_ENABLED, STATE_RX_ENABLED, STATE_BIDIRECTIONAL,
STATE_PAUSED})
public @interface VideoState {}
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 7cd16128..cac9f2b 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -30,6 +30,9 @@
public static final int EUTRAN = 3;
public static final int CDMA2000 = 4;
public static final int IWLAN = 5;
+
+ /** @hide */
+ private AccessNetworkType() {};
}
/**
@@ -42,6 +45,9 @@
public static final int WWAN = 1;
/** Wireless Local Area Networks (i.e. Wifi) */
public static final int WLAN = 2;
+
+ /** @hide */
+ private TransportType() {};
}
/**
@@ -63,6 +69,9 @@
public static final int BAND_DCS1800 = 12;
public static final int BAND_PCS1900 = 13;
public static final int BAND_ER900 = 14;
+
+ /** @hide */
+ private GeranBand() {};
}
/**
@@ -92,6 +101,9 @@
/** band 23, 24 are reserved */
public static final int BAND_25 = 25;
public static final int BAND_26 = 26;
+
+ /** @hide */
+ private UtranBand() {};
}
/**
@@ -147,6 +159,9 @@
public static final int BAND_66 = 66;
public static final int BAND_68 = 68;
public static final int BAND_70 = 70;
+
+ /** @hide */
+ private EutranBand() {};
}
/**
@@ -179,5 +194,11 @@
public static final int BAND_19 = 20;
public static final int BAND_20 = 21;
public static final int BAND_21 = 22;
+
+ /** @hide */
+ private CdmaBands() {};
}
+
+ /** @hide */
+ private AccessNetworkConstants() {};
}
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index a277212..71a177a 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -29,9 +29,9 @@
/**
* The caller of
- * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, NetworkScanCallback)}
+ * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, Executor, NetworkScanCallback)}
* will receive an instance of {@link NetworkScan}, which contains a callback method
- * {@link #stop()} for stopping the in-progress scan.
+ * {@link #stopScan()} for stopping the in-progress scan.
*/
public class NetworkScan {
@@ -106,16 +106,26 @@
* Use this method to stop an ongoing scan. When user requests a new scan, a {@link NetworkScan}
* object will be returned, and the user can stop the scan by calling this method.
*/
- public void stop() throws RemoteException {
+ public void stopScan() {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) {
+ Rlog.e(TAG, "Failed to get the ITelephony instance.");
+ throw new RuntimeException("Failed to get the ITelephony instance.");
+ }
try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- telephony.stopNetworkScan(mSubId, mScanId);
- } else {
- throw new RemoteException("Failed to get the ITelephony instance.");
- }
+ telephony.stopNetworkScan(mSubId, mScanId);
} catch (RemoteException ex) {
Rlog.e(TAG, "stopNetworkScan RemoteException", ex);
+ ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /** @deprecated Use {@link #stopScan()} */
+ @Deprecated
+ public void stop() throws RemoteException {
+ try {
+ stopScan();
+ } catch (RuntimeException ex) {
throw new RemoteException("Failed to stop the network scan with id " + mScanId);
}
}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index b81a214..2074084 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -82,7 +82,7 @@
private int mLteRsrq;
private int mLteRssnr;
private int mLteCqi;
- private int mTdScdmaRscp;
+ private int mTdScdmaRscp; // Valid values are -24...-120dBm or INVALID if unknown
private int mWcdmaSignalStrength;
private int mWcdmaRscpAsu; // the WCDMA RSCP in ASU as reported from the HAL
private int mWcdmaRscp; // the WCDMA RSCP in dBm
@@ -156,6 +156,7 @@
mTdScdmaRscp = INVALID;
mWcdmaSignalStrength = 99;
mWcdmaRscp = INVALID;
+ mWcdmaRscpAsu = 255;
mLteRsrpBoost = 0;
mIsGsm = gsmFlag;
mUseOnlyRsrpForLteLevel = false;
@@ -378,7 +379,7 @@
// but are reported in ASU which is 0 through 96, so we do the conversion here
mWcdmaRscpAsu =
((mWcdmaRscpAsu - 120 >= MIN_WCDMA_RSCP) && (mWcdmaRscpAsu - 120 <= MAX_WCDMA_RSCP))
- ? mWcdmaRscpAsu : INVALID;
+ ? mWcdmaRscpAsu : 255;
mWcdmaRscp = ((mWcdmaRscp >= MIN_WCDMA_RSCP) && (mWcdmaRscp <= MAX_WCDMA_RSCP))
? mWcdmaRscp : INVALID;
@@ -396,8 +397,8 @@
mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
: SignalStrength.INVALID;
- mTdScdmaRscp = ((mTdScdmaRscp >= 25) && (mTdScdmaRscp <= 120))
- ? -mTdScdmaRscp : SignalStrength.INVALID;
+ mTdScdmaRscp = ((mTdScdmaRscp >= 0) && (mTdScdmaRscp <= 96))
+ ? (mTdScdmaRscp - 120) : SignalStrength.INVALID;
// Cqi no change
if (DBG) log("Signal after validate=" + this);
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9f5907b..4d48ed0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -34,6 +34,7 @@
import android.net.ConnectivityManager;
import android.net.NetworkStats;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.BatteryStats;
import android.os.Bundle;
import android.os.Handler;
@@ -73,6 +74,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -5220,21 +5222,35 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
- * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges()
*
* @param request Contains all the RAT with bands/channels that need to be scanned.
+ * @param executor The executor through which the callback should be invoked.
* @param callback Returns network scan results or errors.
* @return A NetworkScan obj which contains a callback which can be used to stop the scan.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public NetworkScan requestNetworkScan(
- NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+ NetworkScanRequest request, Executor executor,
+ TelephonyScanManager.NetworkScanCallback callback) {
synchronized (this) {
if (mTelephonyScanManager == null) {
mTelephonyScanManager = new TelephonyScanManager();
}
}
- return mTelephonyScanManager.requestNetworkScan(getSubId(), request, callback);
+ return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback);
+ }
+
+ /**
+ * @deprecated
+ * Use {@link
+ * #requestNetworkScan(NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+ */
+ @Deprecated
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public NetworkScan requestNetworkScan(
+ NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+ return requestNetworkScan(request, AsyncTask.THREAD_POOL_EXECUTOR, callback);
}
/**
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index c182e34..946cecf 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -33,6 +33,7 @@
import android.util.SparseArray;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.Executor;
import com.android.internal.telephony.ITelephony;
@@ -55,8 +56,10 @@
/**
* The caller of
- * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, NetworkScanCallback)} should
- * implement and provide this callback so that the scan results or errors can be returned.
+ * {@link
+ * TelephonyManager#requestNetworkScan(NetworkScanRequest, Executor, NetworkScanCallback)}
+ * should implement and provide this callback so that the scan results or errors can be
+ * returned.
*/
public static abstract class NetworkScanCallback {
/** Returns the scan results to the user, this callback will be called multiple times. */
@@ -83,10 +86,13 @@
private static class NetworkScanInfo {
private final NetworkScanRequest mRequest;
+ private final Executor mExecutor;
private final NetworkScanCallback mCallback;
- NetworkScanInfo(NetworkScanRequest request, NetworkScanCallback callback) {
+ NetworkScanInfo(
+ NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
mRequest = request;
+ mExecutor = executor;
mCallback = callback;
}
}
@@ -112,10 +118,15 @@
"Failed to find NetworkScanInfo with id " + message.arg2);
}
NetworkScanCallback callback = nsi.mCallback;
+ Executor executor = nsi.mExecutor;
if (callback == null) {
throw new RuntimeException(
"Failed to find NetworkScanCallback with id " + message.arg2);
}
+ if (executor == null) {
+ throw new RuntimeException(
+ "Failed to find Executor with id " + message.arg2);
+ }
switch (message.what) {
case CALLBACK_SCAN_RESULTS:
@@ -126,21 +137,22 @@
for (int i = 0; i < parcelables.length; i++) {
ci[i] = (CellInfo) parcelables[i];
}
- callback.onResults((List<CellInfo>) Arrays.asList(ci));
+ executor.execute(() ->
+ callback.onResults((List<CellInfo>) Arrays.asList(ci)));
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onResults", e);
}
break;
case CALLBACK_SCAN_ERROR:
try {
- callback.onError(message.arg1);
+ executor.execute(() -> callback.onError(message.arg1));
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onError", e);
}
break;
case CALLBACK_SCAN_COMPLETE:
try {
- callback.onComplete();
+ executor.execute(() -> callback.onComplete());
mScanInfo.remove(message.arg2);
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onComplete", e);
@@ -171,12 +183,12 @@
* @hide
*/
public NetworkScan requestNetworkScan(int subId,
- NetworkScanRequest request, NetworkScanCallback callback) {
+ NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
int scanId = telephony.requestNetworkScan(subId, request, mMessenger, new Binder());
- saveScanInfo(scanId, request, callback);
+ saveScanInfo(scanId, request, executor, callback);
return new NetworkScan(scanId, subId);
}
} catch (RemoteException ex) {
@@ -187,9 +199,10 @@
return null;
}
- private void saveScanInfo(int id, NetworkScanRequest request, NetworkScanCallback callback) {
+ private void saveScanInfo(
+ int id, NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
synchronized (mScanInfo) {
- mScanInfo.put(id, new NetworkScanInfo(request, callback));
+ mScanInfo.put(id, new NetworkScanInfo(request, executor, callback));
}
}
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 4907894..a6559e7 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -24,6 +24,7 @@
android.test.runner
LOCAL_PACKAGE_NAME := FrameworksNetTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := platform
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index caaa610..17932a4 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -324,28 +324,26 @@
@Test
public void testEqualsNetCapabilities() {
- int CAPABILITY = NET_CAPABILITY_MMS; // An arbitrary not mutable capability.
-
NetworkCapabilities nc1 = new NetworkCapabilities();
NetworkCapabilities nc2 = new NetworkCapabilities();
assertTrue(nc1.equalsNetCapabilities(nc2));
assertEquals(nc1, nc2);
- nc1.addCapability(CAPABILITY);
+ nc1.addCapability(NET_CAPABILITY_MMS);
assertFalse(nc1.equalsNetCapabilities(nc2));
assertNotEquals(nc1, nc2);
- nc2.addCapability(CAPABILITY);
+ nc2.addCapability(NET_CAPABILITY_MMS);
assertTrue(nc1.equalsNetCapabilities(nc2));
assertEquals(nc1, nc2);
- nc1.addUnwantedCapability(CAPABILITY);
+ nc1.addUnwantedCapability(NET_CAPABILITY_INTERNET);
assertFalse(nc1.equalsNetCapabilities(nc2));
- nc2.addUnwantedCapability(CAPABILITY);
+ nc2.addUnwantedCapability(NET_CAPABILITY_INTERNET);
assertTrue(nc1.equalsNetCapabilities(nc2));
- nc1.removeCapability(CAPABILITY);
+ nc1.removeCapability(NET_CAPABILITY_INTERNET);
assertFalse(nc1.equalsNetCapabilities(nc2));
- nc2.removeCapability(CAPABILITY);
+ nc2.removeCapability(NET_CAPABILITY_INTERNET);
assertTrue(nc1.equalsNetCapabilities(nc2));
}
diff --git a/tools/aapt2/integration-tests/AppOne/Android.mk b/tools/aapt2/integration-tests/AppOne/Android.mk
index 38bd5b5..7b30c4e 100644
--- a/tools/aapt2/integration-tests/AppOne/Android.mk
+++ b/tools/aapt2/integration-tests/AppOne/Android.mk
@@ -19,6 +19,7 @@
include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_PACKAGE_NAME := AaptTestAppOne
+LOCAL_SDK_VERSION := current
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets $(LOCAL_PATH)/assets2
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk b/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
index 012728f..03cce35 100644
--- a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
+++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
@@ -19,5 +19,6 @@
include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_PACKAGE_NAME := AaptAutoVersionTest
+LOCAL_SDK_VERSION := current
LOCAL_MODULE_TAGS := tests
include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/StaticLibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
index 0b7129a..ec4f052 100644
--- a/tools/aapt2/integration-tests/StaticLibOne/Android.mk
+++ b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
@@ -19,6 +19,7 @@
include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_MODULE := AaptTestStaticLibOne
+LOCAL_SDK_VERSION := current
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
index 8b6eb41..40f91af 100644
--- a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
+++ b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
@@ -19,6 +19,7 @@
include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_MODULE := AaptTestStaticLibTwo
+LOCAL_SDK_VERSION := current
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.mk b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
index 902fc65..8da1141 100644
--- a/tools/aapt2/integration-tests/SymlinkTest/Android.mk
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
@@ -19,5 +19,6 @@
include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_PACKAGE_NAME := AaptSymlinkTest
+LOCAL_SDK_VERSION := current
LOCAL_MODULE_TAGS := tests
include $(BUILD_PACKAGE)
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
index c98e40a..8804c8a 100644
--- a/wifi/tests/Android.mk
+++ b/wifi/tests/Android.mk
@@ -60,6 +60,7 @@
android.test.runner \
LOCAL_PACKAGE_NAME := FrameworksWifiApiTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_COMPATIBILITY_SUITE := device-tests
include $(BUILD_PACKAGE)