Merge "Removing some unsed compat APIs"
diff --git a/Android.bp b/Android.bp
index 1586440..7f4756f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -495,6 +495,8 @@
"telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl",
"telephony/java/android/telephony/data/IDataService.aidl",
"telephony/java/android/telephony/data/IDataServiceCallback.aidl",
+ "telephony/java/android/telephony/data/IQualifiedNetworksService.aidl",
+ "telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl",
"telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl",
"telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl",
"telephony/java/android/telephony/ims/aidl/IImsConfig.aidl",
diff --git a/api/system-current.txt b/api/system-current.txt
index d9befc7..6aef50e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4725,6 +4725,7 @@
method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, android.app.NotificationChannel);
method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, android.service.notification.NotificationStats, int);
method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, java.lang.String);
+ method public void onNotificationsSeen(java.util.List<java.lang.String>);
method public final void unsnoozeNotification(java.lang.String);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -4733,6 +4734,7 @@
ctor public NotificationStats();
ctor protected NotificationStats(android.os.Parcel);
method public int describeContents();
+ method public int getDismissalSentiment();
method public int getDismissalSurface();
method public boolean hasDirectReplied();
method public boolean hasExpanded();
@@ -4741,6 +4743,7 @@
method public boolean hasSnoozed();
method public boolean hasViewedSettings();
method public void setDirectReplied();
+ method public void setDismissalSentiment(int);
method public void setDismissalSurface(int);
method public void setExpanded();
method public void setSeen();
@@ -4749,10 +4752,14 @@
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.NotificationStats> CREATOR;
field public static final int DISMISSAL_AOD = 2; // 0x2
- field public static final int DISMISSAL_NOT_DISMISSED = -1; // 0xffffffff
+ field public static final int DISMISSAL_NOT_DISMISSED = -1000; // 0xfffffc18
field public static final int DISMISSAL_OTHER = 0; // 0x0
field public static final int DISMISSAL_PEEK = 1; // 0x1
field public static final int DISMISSAL_SHADE = 3; // 0x3
+ field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
+ field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
+ field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
+ field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
}
public final class SnoozeCriterion implements android.os.Parcelable {
@@ -5546,6 +5553,19 @@
field public static final int RESULT_SUCCESS = 0; // 0x0
}
+ public abstract class QualifiedNetworksService extends android.app.Service {
+ ctor public QualifiedNetworksService();
+ method public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityUpdater createNetworkAvailabilityUpdater(int);
+ field public static final java.lang.String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService";
+ }
+
+ public abstract class QualifiedNetworksService.NetworkAvailabilityUpdater implements java.lang.AutoCloseable {
+ ctor public QualifiedNetworksService.NetworkAvailabilityUpdater(int);
+ method public abstract void close();
+ method public final int getSlotIndex();
+ method public final void updateQualifiedNetworkTypes(int, int[]);
+ }
+
}
package android.telephony.euicc {
@@ -6206,6 +6226,10 @@
field public static final int STATE_UNAVAILABLE = 0; // 0x0
}
+ public static class ImsFeature.Capabilities {
+ field protected int mCapabilities;
+ }
+
protected static class ImsFeature.CapabilityCallbackProxy {
method public void onChangeCapabilityConfigurationError(int, int, int);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 1657de5..33bcce4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5,11 +5,11 @@
field public static final java.lang.String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
field public static final java.lang.String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
field public static final java.lang.String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
+ field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
field public static final java.lang.String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
+ field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
field public static final java.lang.String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
- field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
- field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
}
}
@@ -28,11 +28,11 @@
public class ActivityManager {
method public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
+ method public void forceStopPackage(java.lang.String);
method public int getPackageImportance(java.lang.String);
method public long getTotalRam();
method public int getUidImportance(int);
method public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
- method public void forceStopPackage(java.lang.String);
method public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
}
@@ -53,21 +53,21 @@
}
public class ActivityTaskManager {
+ method public java.lang.String listAllStacks();
+ method public void moveTaskToStack(int, int, boolean);
+ method public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
method public void removeStacksInWindowingModes(int[]) throws java.lang.SecurityException;
method public void removeStacksWithActivityTypes(int[]) throws java.lang.SecurityException;
+ method public void resizeDockedStack(android.graphics.Rect, android.graphics.Rect);
method public void resizeStack(int, android.graphics.Rect) throws java.lang.SecurityException;
- method public void setTaskWindowingMode(int, int, boolean) throws java.lang.SecurityException;
- method public void setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) throws java.lang.SecurityException;
- method public static boolean supportsMultiWindow(android.content.Context);
- method public static boolean supportsSplitScreenMultiWindow(android.content.Context);
- method public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
- method public void startSystemLockTaskMode(int);
- method public void stopSystemLockTaskMode();
- method public void moveTaskToStack(int, int, boolean);
method public void resizeStack(int, android.graphics.Rect, boolean);
method public void resizeTask(int, android.graphics.Rect);
- method public void resizeDockedStack(android.graphics.Rect,android.graphics.Rect);
- method public java.lang.String listAllStacks();
+ method public void setTaskWindowingMode(int, int, boolean) throws java.lang.SecurityException;
+ method public void setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) throws java.lang.SecurityException;
+ method public void startSystemLockTaskMode(int);
+ method public void stopSystemLockTaskMode();
+ method public static boolean supportsMultiWindow(android.content.Context);
+ method public static boolean supportsSplitScreenMultiWindow(android.content.Context);
field public static final int INVALID_STACK_ID = -1; // 0xffffffff
field public static final int SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT = 1; // 0x1
field public static final int SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT = 0; // 0x0
@@ -1025,10 +1025,12 @@
public abstract class InternalSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer {
ctor public InternalSanitizer();
+ method public abstract android.view.autofill.AutofillValue sanitize(android.view.autofill.AutofillValue);
}
public abstract class InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
ctor public InternalTransformation();
+ method public static boolean batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer, android.service.autofill.InternalTransformation>>);
}
public abstract class InternalValidator implements android.os.Parcelable android.service.autofill.Validator {
@@ -1092,6 +1094,7 @@
method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, android.app.NotificationChannel);
method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, java.lang.String);
+ method public void onNotificationsSeen(java.util.List<java.lang.String>);
method public final void unsnoozeNotification(java.lang.String);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -1104,6 +1107,7 @@
ctor public NotificationStats();
ctor protected NotificationStats(android.os.Parcel);
method public int describeContents();
+ method public int getDismissalSentiment();
method public int getDismissalSurface();
method public boolean hasDirectReplied();
method public boolean hasExpanded();
@@ -1112,6 +1116,7 @@
method public boolean hasSnoozed();
method public boolean hasViewedSettings();
method public void setDirectReplied();
+ method public void setDismissalSentiment(int);
method public void setDismissalSurface(int);
method public void setExpanded();
method public void setSeen();
@@ -1120,10 +1125,14 @@
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.NotificationStats> CREATOR;
field public static final int DISMISSAL_AOD = 2; // 0x2
- field public static final int DISMISSAL_NOT_DISMISSED = -1; // 0xffffffff
+ field public static final int DISMISSAL_NOT_DISMISSED = -1000; // 0xfffffc18
field public static final int DISMISSAL_OTHER = 0; // 0x0
field public static final int DISMISSAL_PEEK = 1; // 0x1
field public static final int DISMISSAL_SHADE = 3; // 0x3
+ field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
+ field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
+ field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
+ field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
}
public final class SnoozeCriterion implements android.os.Parcelable {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 466d02b..0497618 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -106,7 +106,6 @@
new AudioModeChangedHandler());
mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter, null, mReceiverHandler);
- mContext.registerReceiver(mProfileBroadcastReceiver, mProfileIntentFilter, null, mReceiverHandler);
}
public void setReceiverHandler(android.os.Handler handler) {
@@ -150,8 +149,7 @@
for (BluetoothDevice device : bondedDevices) {
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (cachedDevice == null) {
- cachedDevice = mDeviceManager.addDevice(device);
- dispatchDeviceAdded(cachedDevice);
+ mDeviceManager.addDevice(device);
deviceAdded = true;
}
}
@@ -276,7 +274,6 @@
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
- BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
// TODO Pick up UUID. They should be available for 2.1 devices.
// Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
@@ -287,8 +284,6 @@
+ cachedDevice);
}
cachedDevice.setRssi(rssi);
- cachedDevice.setBtClass(btClass);
- cachedDevice.setNewName(name);
cachedDevice.setJustDiscovered(true);
}
}
@@ -339,18 +334,9 @@
BluetoothDevice.ERROR);
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (cachedDevice == null) {
- Log.w(TAG, "CachedBluetoothDevice for device " + device +
- " not found, calling readPairedDevices().");
- if (readPairedDevices()) {
- cachedDevice = mDeviceManager.findDevice(device);
- }
-
- if (cachedDevice == null) {
- Log.w(TAG, "Got bonding state changed for " + device +
- ", but we have no record of that device.");
- cachedDevice = mDeviceManager.addDevice(device);
- dispatchDeviceAdded(cachedDevice);
- }
+ Log.w(TAG, "Got bonding state changed for " + device +
+ ", but we have no record of that device.");
+ cachedDevice = mDeviceManager.addDevice(device);
}
synchronized (mCallbacks) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index c511589..33ee569 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -51,13 +51,9 @@
private final BluetoothAdapter mLocalAdapter;
private final LocalBluetoothProfileManager mProfileManager;
private final BluetoothDevice mDevice;
- //TODO: consider remove, BluetoothDevice.getName() is already cached
- private String mName;
private long mHiSyncId;
// Need this since there is no method for getting RSSI
private short mRssi;
- //TODO: consider remove, BluetoothDevice.getBluetoothClass() is already cached
- private BluetoothClass mBtClass;
private HashMap<LocalBluetoothProfile, Integer> mProfileConnectionState;
private final List<LocalBluetoothProfile> mProfiles =
@@ -299,7 +295,7 @@
}
return;
}
- Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName);
+ Log.i(TAG, "Failed to connect " + profile.toString() + " to " + getName());
}
private boolean ensurePaired() {
@@ -376,8 +372,6 @@
// TODO: do any of these need to run async on a background thread?
private void fillData() {
- fetchName();
- fetchBtClass();
updateProfiles();
fetchActiveDevices();
migratePhonebookPermissionChoice();
@@ -400,21 +394,15 @@
return mDevice.getAddress();
}
- public String getName() {
- return mName;
- }
-
/**
- * Populate name from BluetoothDevice.ACTION_FOUND intent
+ * Get name from remote device
+ * @return {@link BluetoothDevice#getAliasName()} if
+ * {@link BluetoothDevice#getAliasName()} is not null otherwise return
+ * {@link BluetoothDevice#getAddress()}
*/
- void setNewName(String name) {
- if (mName == null) {
- mName = name;
- if (mName == null || TextUtils.isEmpty(mName)) {
- mName = mDevice.getAddress();
- }
- dispatchAttributesChanged();
- }
+ public String getName() {
+ final String aliasName = mDevice.getAliasName();
+ return TextUtils.isEmpty(aliasName) ? getAddress() : aliasName;
}
/**
@@ -422,9 +410,8 @@
* @param name new alias name to be set, should never be null
*/
public void setName(String name) {
- // Prevent mName to be set to null if setName(null) is called
- if (name != null && !TextUtils.equals(name, mName)) {
- mName = name;
+ // Prevent getName() to be set to null if setName(null) is called
+ if (name != null && !TextUtils.equals(name, getName())) {
mDevice.setAlias(name);
dispatchAttributesChanged();
}
@@ -461,19 +448,10 @@
}
void refreshName() {
- fetchName();
- dispatchAttributesChanged();
- }
-
- private void fetchName() {
- mName = mDevice.getAliasName();
-
- if (TextUtils.isEmpty(mName)) {
- mName = mDevice.getAddress();
- if (BluetoothUtils.D) {
- Log.d(TAG, "Device has no name (yet), use address: " + mName);
- }
+ if (BluetoothUtils.D) {
+ Log.d(TAG, "Device name: " + getName());
}
+ dispatchAttributesChanged();
}
/**
@@ -606,13 +584,6 @@
return getBondState() == BluetoothDevice.BOND_BONDING;
}
- /**
- * Fetches a new value for the cached BT class.
- */
- private void fetchBtClass() {
- mBtClass = mDevice.getBluetoothClass();
- }
-
private boolean updateProfiles() {
ParcelUuid[] uuids = mDevice.getUuids();
if (uuids == null) return false;
@@ -657,15 +628,6 @@
}
/**
- * Refreshes the UI for the BT class, including fetching the latest value
- * for the class.
- */
- void refreshBtClass() {
- fetchBtClass();
- dispatchAttributesChanged();
- }
-
- /**
* Refreshes the UI when framework alerts us of a UUID change.
*/
void onUuidChanged() {
@@ -715,15 +677,8 @@
}
}
- void setBtClass(BluetoothClass btClass) {
- if (btClass != null && mBtClass != btClass) {
- mBtClass = btClass;
- dispatchAttributesChanged();
- }
- }
-
public BluetoothClass getBtClass() {
- return mBtClass;
+ return mDevice.getBluetoothClass();
}
public List<LocalBluetoothProfile> getProfiles() {
@@ -757,7 +712,7 @@
}
}
- private void dispatchAttributesChanged() {
+ void dispatchAttributesChanged() {
synchronized (mCallbacks) {
for (Callback callback : mCallbacks) {
callback.onDeviceAttributesChanged();
@@ -805,7 +760,7 @@
if (comparison != 0) return comparison;
// Fallback on name
- return mName.compareTo(another.mName);
+ return getName().compareTo(another.getName());
}
public interface Callback {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index f8543fc..47bd853 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -260,7 +260,7 @@
public synchronized void onBtClassChanged(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = findDevice(device);
if (cachedDevice != null) {
- cachedDevice.refreshBtClass();
+ cachedDevice.dispatchAttributesChanged();
}
}
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 5e417c3..c18db11 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
@@ -606,4 +606,35 @@
assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
}
+
+ @Test
+ public void getName_aliasNameNotNull_returnAliasName() {
+ when(mDevice.getAliasName()).thenReturn(DEVICE_NAME);
+
+ assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_NAME);
+ }
+
+ @Test
+ public void getName_aliasNameIsNull_returnAddress() {
+ when(mDevice.getAliasName()).thenReturn(null);
+
+ assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_ADDRESS);
+ }
+
+ @Test
+ public void setName_setDeviceNameIsNotNull() {
+ final String name = "test name";
+ when(mDevice.getAliasName()).thenReturn(DEVICE_NAME);
+
+ mCachedDevice.setName(name);
+
+ verify(mDevice).setAlias(name);
+ }
+
+ @Test
+ public void setName_setDeviceNameIsNull() {
+ mCachedDevice.setName(null);
+
+ verify(mDevice, never()).setAlias(any());
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index f223176..e05f9fd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -241,6 +241,7 @@
mShadowBluetoothAdapter.setSupportedProfiles(null);
mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
mDeviceManager, mEventManager);
+ mEventManager.registerProfileIntentReceiver();
// Refer to BluetoothControllerImpl, it will call setReceiverHandler after
// LocalBluetoothProfileManager created.
mEventManager.setReceiverHandler(null);
diff --git a/packages/SystemUI/res/drawable-ldrtl/ic_sysbar_back_carmode.xml b/packages/SystemUI/res/drawable-ldrtl/ic_sysbar_back_carmode.xml
deleted file mode 100644
index f91190b..0000000
--- a/packages/SystemUI/res/drawable-ldrtl/ic_sysbar_back_carmode.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="44dp"
- android:height="44dp"
- android:viewportWidth="44.0"
- android:viewportHeight="44.0">
- <path
- android:pathData="M35,21.94C35,22.78 34.49,23.58 33.64,24.05L12.44,36.13C11.43,36.7 10.58,36.51 10.11,36.25C9.08,35.67 9,34.56 9,34.09L9,9.91C9,9.35 9.08,8.31 10.09,7.75C10.54,7.49 11.34,7.31 12.33,7.86L33.74,19.95C34.51,20.39 35,21.13 35,21.94L35,21.94ZM12.5,32L30.5,21.96L12.5,12L12.5,32Z"
- android:strokeColor="#00000000"
- android:fillType="evenOdd"
- android:fillColor="#F8F9FA"
- android:strokeWidth="1"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back_ime_carmode.xml b/packages/SystemUI/res/drawable/ic_sysbar_back_ime_carmode.xml
deleted file mode 100644
index 542ba9b..0000000
--- a/packages/SystemUI/res/drawable/ic_sysbar_back_ime_carmode.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="44dp"
- android:height="44dp"
- android:viewportWidth="44.0"
- android:viewportHeight="44.0">
- <path
- android:pathData="M22.06,35C21.22,35 20.42,34.49 19.95,33.64L7.87,12.44C7.3,11.43 7.49,10.58 7.75,10.11C8.33,9.08 9.44,9 9.91,9L34.09,9C34.65,9 35.69,9.08 36.25,10.09C36.51,10.54 36.69,11.34 36.14,12.33L24.05,33.74C23.61,34.51 22.87,35 22.06,35L22.06,35ZM12,12.5L22.04,30.5L32,12.5L12,12.5Z"
- android:strokeColor="#00000000"
- android:fillType="evenOdd"
- android:fillColor="#F8F9FA"
- android:strokeWidth="1"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/qs_customize_header.xml b/packages/SystemUI/res/layout/qs_customize_header.xml
new file mode 100644
index 0000000..57cf83f
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_customize_header.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textAppearance="@android:style/TextAppearance.Material.Body2"
+ android:minHeight="28dp"
+ android:textColor="?android:attr/colorAccent"
+ android:text="@string/drag_to_rearrange_tiles" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
index 4ce6ef6..bb67c54 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -43,7 +43,6 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
- android:paddingTop="28dp"
android:paddingLeft="@dimen/qs_tile_layout_margin_side"
android:paddingRight="@dimen/qs_tile_layout_margin_side"
android:paddingBottom="28dp"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c113745d..2deec5e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1869,6 +1869,9 @@
<!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
<string name="drag_to_add_tiles">Hold and drag to add tiles</string>
+ <!-- Label for header of customize QS [CHAR LIMIT=60] -->
+ <string name="drag_to_rearrange_tiles">Hold and drag to rearrange tiles</string>
+
<!-- Label for area where tiles can be dragged in to [CHAR LIMIT=60] -->
<string name="drag_to_remove_tiles">Drag here to remove</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 10b92f7..92f5cae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -62,6 +62,7 @@
private static final int TYPE_TILE = 0;
private static final int TYPE_EDIT = 1;
private static final int TYPE_ACCESSIBLE_DROP = 2;
+ private static final int TYPE_HEADER = 3;
private static final int TYPE_DIVIDER = 4;
private static final long EDIT_ID = 10000;
@@ -112,7 +113,7 @@
public void saveSpecs(QSTileHost host) {
List<String> newSpecs = new ArrayList<>();
- for (int i = 0; i < mTiles.size() && mTiles.get(i) != null; i++) {
+ for (int i = 1; i < mTiles.size() && mTiles.get(i) != null; i++) {
newSpecs.add(mTiles.get(i).spec);
}
host.changeTiles(mCurrentSpecs, newSpecs);
@@ -145,6 +146,7 @@
}
mOtherTiles = new ArrayList<TileInfo>(mAllTiles);
mTiles.clear();
+ mTiles.add(null);
for (int i = 0; i < mCurrentSpecs.size(); i++) {
final TileInfo tile = getAndRemoveOther(mCurrentSpecs.get(i));
if (tile != null) {
@@ -177,6 +179,9 @@
@Override
public int getItemViewType(int position) {
+ if (position == 0) {
+ return TYPE_HEADER;
+ }
if (mAccessibilityAction == ACTION_ADD && position == mEditIndex - 1) {
return TYPE_ACCESSIBLE_DROP;
}
@@ -193,6 +198,9 @@
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
final Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
+ if (viewType == TYPE_HEADER) {
+ return new Holder(inflater.inflate(R.layout.qs_customize_header, parent, false));
+ }
if (viewType == TYPE_DIVIDER) {
return new Holder(inflater.inflate(R.layout.qs_customize_tile_divider, parent, false));
}
@@ -218,6 +226,9 @@
@Override
public void onBindViewHolder(final Holder holder, int position) {
+ if (holder.getItemViewType() == TYPE_HEADER) {
+ return;
+ }
if (holder.getItemViewType() == TYPE_DIVIDER) {
holder.itemView.setVisibility(mTileDividerIndex < mTiles.size() - 1 ? View.VISIBLE
: View.INVISIBLE);
@@ -243,7 +254,7 @@
holder.mTileView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
holder.mTileView.setContentDescription(mContext.getString(
R.string.accessibility_qs_edit_tile_add, mAccessibilityFromLabel,
- position + 1));
+ position));
holder.mTileView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -274,13 +285,13 @@
R.string.accessibility_qs_edit_add_tile_label, info.state.label);
} else if (mAccessibilityAction == ACTION_ADD) {
info.state.contentDescription = mContext.getString(
- R.string.accessibility_qs_edit_tile_add, mAccessibilityFromLabel, position + 1);
+ R.string.accessibility_qs_edit_tile_add, mAccessibilityFromLabel, position);
} else if (mAccessibilityAction == ACTION_MOVE) {
info.state.contentDescription = mContext.getString(
- R.string.accessibility_qs_edit_tile_move, mAccessibilityFromLabel, position + 1);
+ R.string.accessibility_qs_edit_tile_move, mAccessibilityFromLabel, position);
} else {
info.state.contentDescription = mContext.getString(
- R.string.accessibility_qs_edit_tile_label, position + 1, info.state.label);
+ R.string.accessibility_qs_edit_tile_label, position, info.state.label);
}
holder.mTileView.handleStateChanged(info.state);
holder.mTileView.setShowAppLabel(position > mEditIndex && !info.isSystem);
@@ -403,11 +414,12 @@
}
private void updateDividerLocations() {
- // The first null is the edit tiles label, the second null is the tile divider.
- // If there is no second null, then there are no non-system tiles.
+ // The first null is the header label (index 0) so we can skip it,
+ // the second null is the edit tiles label, the third null is the tile divider.
+ // If there is no third null, then there are no non-system tiles.
mEditIndex = -1;
mTileDividerIndex = mTiles.size();
- for (int i = 0; i < mTiles.size(); i++) {
+ for (int i = 1; i < mTiles.size(); i++) {
if (mTiles.get(i) == null) {
if (mEditIndex == -1) {
mEditIndex = i;
@@ -486,7 +498,7 @@
@Override
public int getSpanSize(int position) {
final int type = getItemViewType(position);
- return type == TYPE_EDIT || type == TYPE_DIVIDER ? 3 : 1;
+ return type == TYPE_EDIT || type == TYPE_DIVIDER || type == TYPE_HEADER ? 3 : 1;
}
};
@@ -511,7 +523,8 @@
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final ViewHolder holder = parent.getChildViewHolder(child);
- if (holder.getAdapterPosition() < mEditIndex && !(child instanceof TextView)) {
+ if (holder.getAdapterPosition() == 0 ||
+ holder.getAdapterPosition() < mEditIndex && !(child instanceof TextView)) {
continue;
}
@@ -569,6 +582,9 @@
@Override
public boolean canDropOver(RecyclerView recyclerView, ViewHolder current,
ViewHolder target) {
+ if (target.getAdapterPosition() == 0){
+ return false;
+ }
if (!canRemoveTiles() && current.getAdapterPosition() < mEditIndex) {
return target.getAdapterPosition() < mEditIndex;
}
@@ -577,12 +593,17 @@
@Override
public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {
- if (viewHolder.getItemViewType() == TYPE_EDIT || viewHolder.getItemViewType() == TYPE_DIVIDER) {
- return makeMovementFlags(0, 0);
+ switch (viewHolder.getItemViewType()) {
+ case TYPE_EDIT:
+ case TYPE_DIVIDER:
+ case TYPE_HEADER:
+ // Fall through
+ return makeMovementFlags(0, 0);
+ default:
+ int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN
+ | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT;
+ return makeMovementFlags(dragFlags, 0);
}
- int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT
- | ItemTouchHelper.LEFT;
- return makeMovementFlags(dragFlags, 0);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 3e41cd2..0d9c623 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -123,9 +123,9 @@
private Rect mTmpRect = new Rect();
private KeyButtonDrawable mBackIcon;
- private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
- private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
- private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
+ private KeyButtonDrawable mHomeDefaultIcon;
+ private KeyButtonDrawable mBackCarModeIcon;
+ private KeyButtonDrawable mHomeCarModeIcon;
private KeyButtonDrawable mRecentIcon;
private KeyButtonDrawable mDockedIcon;
private KeyButtonDrawable mImeIcon;
@@ -461,16 +461,9 @@
&& ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
}
- // TODO(b/80003212): change car mode icons to vector icons.
private void updateCarModeIcons(Context ctx) {
- mBackCarModeIcon = getDrawable(ctx,
- R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
- mBackLandCarModeIcon = mBackCarModeIcon;
- mBackAltCarModeIcon = getDrawable(ctx,
- R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
- mBackAltLandCarModeIcon = mBackAltCarModeIcon;
- mHomeCarModeIcon = getDrawable(ctx,
- R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
+ mBackCarModeIcon = getDrawable(ctx, R.drawable.ic_sysbar_back_carmode);
+ mHomeCarModeIcon = getDrawable(ctx, R.drawable.ic_sysbar_home_carmode);
}
private void reloadNavIcons() {
@@ -575,11 +568,9 @@
darkContext.getDrawable(icon), hasShadow);
}
- private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
- @DrawableRes int darkIcon) {
- // Legacy image icons using separate light and dark images will not support shadows
- return KeyButtonDrawable.create(ctx, ctx.getDrawable(lightIcon),
- ctx.getDrawable(darkIcon), false /* hasShadow */);
+ private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon) {
+ // Legacy image icons using a single image will not support shadows
+ return KeyButtonDrawable.create(ctx, ctx.getDrawable(icon), null, false /* hasShadow */);
}
private TintedKeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
@@ -594,16 +585,8 @@
super.setLayoutDirection(layoutDirection);
}
- private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
- return landscape
- ? carMode ? mBackAltLandCarModeIcon : mBackIcon
- : carMode ? mBackAltCarModeIcon : mBackIcon;
- }
-
- private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
- return landscape
- ? carMode ? mBackLandCarModeIcon : mBackIcon
- : carMode ? mBackCarModeIcon : mBackIcon;
+ private KeyButtonDrawable getBackIcon(boolean carMode) {
+ return carMode ? mBackCarModeIcon : mBackIcon;
}
public void setNavigationIconHints(int hints) {
@@ -643,12 +626,10 @@
// to recent icon is not required.
final boolean useAltBack =
(mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
- KeyButtonDrawable backIcon = useAltBack
- ? getBackIconWithAlt(mUseCarModeUi, mVertical)
- : getBackIcon(mUseCarModeUi, mVertical);
+ KeyButtonDrawable backIcon = getBackIcon(mUseCarModeUi);
+ orientBackButton(backIcon);
KeyButtonDrawable homeIcon = mUseCarModeUi ? mHomeCarModeIcon : mHomeDefaultIcon;
if (!mUseCarModeUi) {
- orientBackButton(backIcon);
orientHomeButton(homeIcon);
}
getHomeButton().setImageDrawable(homeIcon);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
index 214dda2..9c9b929 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
@@ -60,7 +60,7 @@
if (mEventBuf.size() == MAX_EVENTS) {
mEventBuf.remove();
}
- mEventBuf.add(new MotionEventCopy(event.getX(), event.getY(), event.getEventTime()));
+ mEventBuf.add(new MotionEventCopy(event.getRawX(), event.getRawY(), event.getEventTime()));
}
public void computeCurrentVelocity(int units) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7812a14..7b9dc0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -227,13 +227,7 @@
}
private void trackMovement(MotionEvent event) {
- // Add movement to velocity tracker using raw screen X and Y coordinates instead
- // of window coordinates because the window frame may be moving at the same time.
- float deltaX = event.getRawX() - event.getX();
- float deltaY = event.getRawY() - event.getY();
- event.offsetLocation(deltaX, deltaY);
if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
- event.offsetLocation(-deltaX, -deltaY);
}
public void setTouchDisabled(boolean disabled) {
diff --git a/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl
new file mode 100644
index 0000000..9c80cb7
--- /dev/null
+++ b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 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 android.telephony.data;
+
+import android.telephony.data.IQualifiedNetworksServiceCallback;
+
+/**
+ * {@hide}
+ */
+interface IQualifiedNetworksService
+{
+ oneway void createNetworkAvailabilityUpdater(int slotId, IQualifiedNetworksServiceCallback callback);
+ oneway void removeNetworkAvailabilityUpdater(int slotId);
+}
diff --git a/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl b/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl
new file mode 100644
index 0000000..e8e1f01
--- /dev/null
+++ b/telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 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 android.telephony.data;
+
+/**
+ * The qualified networks service call back interface
+ * @hide
+ */
+oneway interface IQualifiedNetworksServiceCallback
+{
+ void onQualifiedNetworkTypesChanged(int apnType, in int[] qualifiedNetworkTypesList);
+}
diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java
new file mode 100644
index 0000000..bb89f19
--- /dev/null
+++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright 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 android.telephony.data;
+
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.Rlog;
+import android.telephony.data.ApnSetting.ApnType;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Base class of the qualified networks service. Services that extend QualifiedNetworksService must
+ * register the service in their AndroidManifest to be detected by the framework. They must be
+ * protected by the permission "android.permission.BIND_TELEPHONY_QUALIFIED_NETWORKS_SERVICE".
+ * The qualified networks service definition in the manifest must follow the following format:
+ * ...
+ * <service android:name=".xxxQualifiedNetworksService"
+ * android:permission="android.permission.BIND_TELEPHONY_QUALIFIED_NETWORKS_SERVICE" >
+ * <intent-filter>
+ * <action android:name="android.telephony.data.QualifiedNetworksService" />
+ * </intent-filter>
+ * </service>
+ * @hide
+ */
+@SystemApi
+public abstract class QualifiedNetworksService extends Service {
+ private static final String TAG = QualifiedNetworksService.class.getSimpleName();
+
+ public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE =
+ "android.telephony.data.QualifiedNetworksService";
+
+ private static final int QNS_CREATE_NETWORK_AVAILABILITY_UPDATER = 1;
+ private static final int QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER = 2;
+ private static final int QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS = 3;
+ private static final int QNS_UPDATE_QUALIFIED_NETWORKS = 4;
+
+ private final HandlerThread mHandlerThread;
+
+ private final QualifiedNetworksServiceHandler mHandler;
+
+ private final SparseArray<NetworkAvailabilityUpdater> mUpdaters = new SparseArray<>();
+
+ /** @hide */
+ @VisibleForTesting
+ public final IQualifiedNetworksServiceWrapper mBinder = new IQualifiedNetworksServiceWrapper();
+
+ /**
+ * The abstract class of the network availability updater implementation. The vendor qualified
+ * network service must extend this class to report the available networks for data
+ * connection setup. Note that each instance of network availability updater is associated with
+ * one physical SIM slot.
+ */
+ public abstract class NetworkAvailabilityUpdater implements AutoCloseable {
+ private final int mSlotIndex;
+
+ private IQualifiedNetworksServiceCallback mCallback;
+
+ /**
+ * Qualified networks for each APN type. Key is the {@link ApnType}, value is the array
+ * of available networks.
+ */
+ private SparseArray<int[]> mQualifiedNetworkTypesList = new SparseArray<>();
+
+ /**
+ * Constructor
+ * @param slotIndex SIM slot index the network availability updater associated with.
+ */
+ public NetworkAvailabilityUpdater(int slotIndex) {
+ mSlotIndex = slotIndex;
+ }
+
+ /**
+ * @return SIM slot index the network availability updater associated with.
+ */
+ public final int getSlotIndex() {
+ return mSlotIndex;
+ }
+
+ private void registerForQualifiedNetworkTypesChanged(
+ IQualifiedNetworksServiceCallback callback) {
+ mCallback = callback;
+
+ // Force sending the qualified networks upon registered.
+ if (mCallback != null) {
+ for (int i = 0; i < mQualifiedNetworkTypesList.size(); i++) {
+ try {
+ mCallback.onQualifiedNetworkTypesChanged(
+ mQualifiedNetworkTypesList.keyAt(i),
+ mQualifiedNetworkTypesList.valueAt(i));
+ } catch (RemoteException e) {
+ loge("Failed to call onQualifiedNetworksChanged. " + e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Update the qualified networks list. Network availability updater must invoke this method
+ * whenever the qualified networks changes. If this method is never invoked for certain
+ * APN type, then frameworks will always use the default (i.e. cellular) data and network
+ * service.
+ *
+ * @param apnType APN type of the qualified networks
+ * @param qualifiedNetworkTypes List of network types which are qualified for data
+ * connection setup for {@link @apnType} in the preferred order. Each element in the array
+ * is a {@link AccessNetworkType}. An empty list or null indicates no networks are qualified
+ * for data setup.
+ */
+ public final void updateQualifiedNetworkTypes(@ApnType int apnType,
+ int[] qualifiedNetworkTypes) {
+ mHandler.obtainMessage(QNS_UPDATE_QUALIFIED_NETWORKS, mSlotIndex, apnType,
+ qualifiedNetworkTypes).sendToTarget();
+ }
+
+ private void onUpdateQualifiedNetworkTypes(@ApnType int apnType,
+ int[] qualifiedNetworkTypes) {
+ mQualifiedNetworkTypesList.put(apnType, qualifiedNetworkTypes);
+ if (mCallback != null) {
+ try {
+ mCallback.onQualifiedNetworkTypesChanged(apnType, qualifiedNetworkTypes);
+ } catch (RemoteException e) {
+ loge("Failed to call onQualifiedNetworksChanged. " + e);
+ }
+ }
+ }
+
+ /**
+ * Called when the qualified networks updater is removed. The extended class should
+ * implement this method to perform clean up works.
+ */
+ @Override
+ public abstract void close();
+ }
+
+ private class QualifiedNetworksServiceHandler extends Handler {
+ QualifiedNetworksServiceHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ IQualifiedNetworksServiceCallback callback;
+ final int slotIndex = message.arg1;
+ NetworkAvailabilityUpdater updater = mUpdaters.get(slotIndex);
+
+ switch (message.what) {
+ case QNS_CREATE_NETWORK_AVAILABILITY_UPDATER:
+ if (mUpdaters.get(slotIndex) != null) {
+ loge("Network availability updater for slot " + slotIndex
+ + " already existed.");
+ return;
+ }
+
+ updater = createNetworkAvailabilityUpdater(slotIndex);
+ if (updater != null) {
+ mUpdaters.put(slotIndex, updater);
+
+ callback = (IQualifiedNetworksServiceCallback) message.obj;
+ updater.registerForQualifiedNetworkTypesChanged(callback);
+ } else {
+ loge("Failed to create network availability updater. slot index = "
+ + slotIndex);
+ }
+ break;
+
+ case QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER:
+ if (updater != null) {
+ updater.close();
+ mUpdaters.remove(slotIndex);
+ }
+ break;
+
+ case QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS:
+ for (int i = 0; i < mUpdaters.size(); i++) {
+ updater = mUpdaters.get(i);
+ if (updater != null) {
+ updater.close();
+ }
+ }
+ mUpdaters.clear();
+ break;
+
+ case QNS_UPDATE_QUALIFIED_NETWORKS:
+ if (updater == null) break;
+ updater.onUpdateQualifiedNetworkTypes(message.arg2, (int[]) message.obj);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Default constructor.
+ */
+ public QualifiedNetworksService() {
+ mHandlerThread = new HandlerThread(TAG);
+ mHandlerThread.start();
+
+ mHandler = new QualifiedNetworksServiceHandler(mHandlerThread.getLooper());
+ log("Qualified networks service created");
+ }
+
+ /**
+ * Create the instance of {@link NetworkAvailabilityUpdater}. Vendor qualified network service
+ * must override this method to facilitate the creation of {@link NetworkAvailabilityUpdater}
+ * instances. The system will call this method after binding the qualified networks service for
+ * each active SIM slot index.
+ *
+ * @param slotIndex SIM slot index the qualified networks service associated with.
+ * @return Qualified networks service instance
+ */
+ public abstract NetworkAvailabilityUpdater createNetworkAvailabilityUpdater(int slotIndex);
+
+ /** @hide */
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (intent == null || !QUALIFIED_NETWORKS_SERVICE_INTERFACE.equals(intent.getAction())) {
+ loge("Unexpected intent " + intent);
+ return null;
+ }
+ return mBinder;
+ }
+
+ /** @hide */
+ @Override
+ public boolean onUnbind(Intent intent) {
+ mHandler.obtainMessage(QNS_REMOVE_ALL_NETWORK_AVAILABILITY_UPDATERS).sendToTarget();
+ return false;
+ }
+
+ /** @hide */
+ @Override
+ public void onDestroy() {
+ mHandlerThread.quit();
+ }
+
+ /**
+ * A wrapper around IQualifiedNetworksService that forwards calls to implementations of
+ * {@link QualifiedNetworksService}.
+ */
+ private class IQualifiedNetworksServiceWrapper extends IQualifiedNetworksService.Stub {
+ @Override
+ public void createNetworkAvailabilityUpdater(int slotIndex,
+ IQualifiedNetworksServiceCallback callback) {
+ mHandler.obtainMessage(QNS_CREATE_NETWORK_AVAILABILITY_UPDATER, slotIndex, 0,
+ callback).sendToTarget();
+ }
+
+ @Override
+ public void removeNetworkAvailabilityUpdater(int slotIndex) {
+ mHandler.obtainMessage(QNS_REMOVE_NETWORK_AVAILABILITY_UPDATER, slotIndex, 0)
+ .sendToTarget();
+ }
+ }
+
+ private void log(String s) {
+ Rlog.d(TAG, s);
+ }
+
+ private void loge(String s) {
+ Rlog.e(TAG, s);
+ }
+}