Merge "Enable emergency dialer shortcuts feature"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ac8d18a..ce774d8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -65,6 +65,7 @@
<protected-broadcast android:name= "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE" />
<protected-broadcast android:name= "com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
<protected-broadcast android:name= "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE" />
+ <protected-broadcast android:name= "com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED" />
<protected-broadcast android:name= "com.android.internal.provider.action.VOICEMAIL_SMS_RECEIVED" />
<protected-broadcast android:name= "com.android.intent.isim_refresh" />
<protected-broadcast android:name= "com.android.ims.ACTION_RCS_SERVICE_AVAILABLE" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d6c5fd7..b3889dd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -530,6 +530,16 @@
<!-- Mobile network 4G summary [CHAR LIMIT=80] -->
<string name="enhanced_4g_lte_mode_summary">Use LTE services to improve voice and other communications (recommended)</string>
+ <string name="enhanced_4g_lte_mode_summary_o2">Use 4G services to improve voice and other communications (recommended)</string>
+ <!-- Carrier variant of Enhaced 4G LTE Mode summary. [CHAR LIMIT=80] -->
+ <string-array name="enhanced_4g_lte_mode_sumary_variant">
+ <!-- 0: Default -->
+ <item>@string/enhanced_4g_lte_mode_summary</item>
+ <!-- 1: Verizon -->
+ <item>@string/enhanced_4g_lte_mode_summary</item>
+ <!-- 2: O2 UK -->
+ <item>@string/enhanced_4g_lte_mode_summary_o2</item>
+ </string-array>
<!-- Mobile network settings screen, data enabling checkbox name -->
<string name="data_enabled">Data enabled</string>
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 125c01a..86babd5 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -1149,15 +1149,22 @@
CarrierConfigManager.KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT);
CharSequence[] variantTitles = getContext().getResources()
.getTextArray(R.array.enhanced_4g_lte_mode_title_variant);
- // Default index 0 indicates the default title string
+ CharSequence[] variantSumaries = getContext().getResources()
+ .getTextArray(R.array.enhanced_4g_lte_mode_sumary_variant);
+ // Default index 0 indicates the default title/sumary string
CharSequence enhanced4glteModeTitle = variantTitles[0];
+ CharSequence enhanced4glteModeSummary = variantSumaries[0];
if (variant4glteTitleIndex >= 0 && variant4glteTitleIndex < variantTitles.length) {
enhanced4glteModeTitle = variantTitles[variant4glteTitleIndex];
}
+ if (variant4glteTitleIndex >= 0 && variant4glteTitleIndex < variantSumaries.length) {
+ enhanced4glteModeSummary = variantSumaries[variant4glteTitleIndex];
+ }
mOnlyAutoSelectInHomeNW = carrierConfig.getBoolean(
CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL);
mButton4glte.setTitle(enhanced4glteModeTitle);
+ mButton4glte.setSummary(enhanced4glteModeSummary);
mLteDataServicePref.setEnabled(hasActiveSubscriptions);
Preference ps;
ps = findPreference(BUTTON_CELL_BROADCAST_SETTINGS);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 5401ddc..bf0ce15 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -60,6 +60,7 @@
import android.telephony.CellInfoWcdma;
import android.telephony.CellLocation;
import android.telephony.ClientRequestStats;
+import android.telephony.ICellInfoCallback;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.LocationAccessPolicy;
import android.telephony.ModemActivityInfo;
@@ -82,6 +83,7 @@
import android.telephony.gsm.GsmCellLocation;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
@@ -217,6 +219,8 @@
private static final int EVENT_GET_CELL_LOCATION_DONE = 63;
private static final int CMD_MODEM_REBOOT = 64;
private static final int EVENT_CMD_MODEM_REBOOT_DONE = 65;
+ private static final int CMD_REQUEST_CELL_INFO_UPDATE = 66;
+ private static final int EVENT_REQUEST_CELL_INFO_UPDATE_DONE = 67;
// Parameters of select command.
private static final int SELECT_COMMAND = 0xA4;
@@ -1000,13 +1004,11 @@
request.result = ar.exception == null;
notifyRequester(request);
break;
-
case CMD_GET_ALL_CELL_INFO:
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_GET_ALL_CELL_INFO_DONE, request);
request.phone.requestCellInfoUpdate(request.workSource, onCompleted);
break;
-
case EVENT_GET_ALL_CELL_INFO_DONE:
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
@@ -1017,22 +1019,45 @@
request.notifyAll();
}
break;
-
- case CMD_GET_CELL_LOCATION: {
+ case CMD_REQUEST_CELL_INFO_UPDATE:
+ request = (MainThreadRequest) msg.obj;
+ request.phone.requestCellInfoUpdate(request.workSource,
+ obtainMessage(EVENT_REQUEST_CELL_INFO_UPDATE_DONE, request));
+ break;
+ case EVENT_REQUEST_CELL_INFO_UPDATE_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ ICellInfoCallback cb = (ICellInfoCallback) request.argument;
+ try {
+ if (ar.exception != null) {
+ // something went wrong... the response is null
+ Log.e(LOG_TAG, "Exception retrieving CellInfo=" + ar.exception);
+ cb.onCellInfo(null);
+ } else if (ar.result == null) {
+ // timeout occurred, so force the result to non-null "empty"
+ Log.w(LOG_TAG, "Timeout Waiting for CellInfo!");
+ cb.onCellInfo(new ArrayList<CellInfo>());
+ } else {
+ // use the result as returned
+ cb.onCellInfo((List<CellInfo>) ar.result);
+ }
+ } catch (RemoteException re) {
+ Log.w(LOG_TAG, "Discarded CellInfo due to Callback RemoteException");
+ }
+ break;
+ case CMD_GET_CELL_LOCATION:
request = (MainThreadRequest) msg.obj;
WorkSource ws = (WorkSource) request.argument;
Phone phone = getPhoneFromRequest(request);
phone.getCellLocation(ws, obtainMessage(EVENT_GET_CELL_LOCATION_DONE, request));
break;
- }
-
- case EVENT_GET_CELL_LOCATION_DONE: {
+ case EVENT_GET_CELL_LOCATION_DONE:
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
if (ar.exception == null) {
request.result = ar.result;
} else {
- Phone phone = getPhoneFromRequest(request);
+ phone = getPhoneFromRequest(request);
request.result = (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
? new CdmaCellLocation() : new GsmCellLocation();
}
@@ -1041,18 +1066,14 @@
request.notifyAll();
}
break;
- }
-
case CMD_MODEM_REBOOT:
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
mPhone.rebootModem(onCompleted);
break;
-
case EVENT_CMD_MODEM_REBOOT_DONE:
handleNullReturnEvent(msg, "rebootModem");
break;
-
default:
Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
break;
@@ -1178,10 +1199,19 @@
/**
* Same as {@link #sendRequestAsync(int)} except it takes an argument.
- * @see {@link #sendRequest(int,Object)}
+ * @see {@link #sendRequest(int)}
*/
private void sendRequestAsync(int command, Object argument) {
- MainThreadRequest request = new MainThreadRequest(argument);
+ sendRequestAsync(command, argument, null, null);
+ }
+
+ /**
+ * Same as {@link #sendRequestAsync(int,Object)} except it takes a Phone and WorkSource.
+ * @see {@link #sendRequest(int,Object)}
+ */
+ private void sendRequestAsync(
+ int command, Object argument, Phone phone, WorkSource workSource) {
+ MainThreadRequest request = new MainThreadRequest(argument, phone, workSource);
Message msg = mMainThreadHandler.obtainMessage(command, request);
msg.sendToTarget();
}
@@ -1915,6 +1945,14 @@
return (neighbors.size()) > 0 ? neighbors : null;
}
+ private List<CellInfo> getCachedCellInfo() {
+ List<CellInfo> cellInfos = new ArrayList<CellInfo>();
+ for (Phone phone : PhoneFactory.getPhones()) {
+ List<CellInfo> info = phone.getAllCellInfo();
+ if (info != null) cellInfos.addAll(info);
+ }
+ return cellInfos;
+ }
@Override
public List<CellInfo> getAllCellInfo(String callingPackage) {
@@ -1925,6 +1963,11 @@
return null;
}
+ final int targetSdk = getTargetSdk(callingPackage);
+ if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
+ return getCachedCellInfo();
+ }
+
if (DBG_LOC) log("getAllCellInfo: is active user");
WorkSource workSource = getWorkSource(Binder.getCallingUid());
final long identity = Binder.clearCallingIdentity();
@@ -1942,6 +1985,34 @@
}
@Override
+ public void requestCellInfoUpdate(int subId, ICellInfoCallback cb, String callingPackage) {
+ requestCellInfoUpdateInternal(
+ subId, cb, callingPackage, getWorkSource(Binder.getCallingUid()));
+ }
+
+ @Override
+ public void requestCellInfoUpdateWithWorkSource(
+ int subId, ICellInfoCallback cb, String callingPackage, WorkSource workSource) {
+ enforceModifyPermission();
+ requestCellInfoUpdateInternal(subId, cb, callingPackage, workSource);
+ }
+
+ private void requestCellInfoUpdateInternal(
+ int subId, ICellInfoCallback cb, String callingPackage, WorkSource workSource) {
+ mPhone.getContext().getSystemService(AppOpsManager.class)
+ .checkPackage(Binder.getCallingUid(), callingPackage);
+ if (!LocationAccessPolicy.canAccessCellLocation(mPhone.getContext(),
+ callingPackage, Binder.getCallingUid(), Binder.getCallingPid(), true)) {
+ return;
+ }
+
+ final Phone phone = getPhone(subId);
+ if (phone == null) throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
+
+ sendRequestAsync(CMD_REQUEST_CELL_INFO_UPDATE, cb, phone, workSource);
+ }
+
+ @Override
public void setCellInfoListRate(int rateInMillis) {
enforceModifyPermission();
WorkSource workSource = getWorkSource(Binder.getCallingUid());
@@ -2905,6 +2976,98 @@
}
}
+ @Override
+ public void registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
+ enforceReadPrivilegedPermission("registerImsProvisioningChangedCallback");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ ImsManager.getInstance(mPhone.getContext(), getSlotIndexOrException(subId))
+ .getConfigInterface().addConfigCallback(callback);
+ } catch (ImsException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
+ enforceReadPrivilegedPermission("unregisterImsProvisioningChangedCallback");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ ImsManager.getInstance(mPhone.getContext(), getSlotIndexOrException(subId))
+ .getConfigInterface().removeConfigCallback(callback);
+ } catch (ImsException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public int getImsProvisioningInt(int subId, int key) {
+ enforceReadPrivilegedPermission("getImsProvisioningInt");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ return ImsManager.getInstance(mPhone.getContext(), getSlotIndexOrException(subId))
+ .getConfigInterface().getConfigInt(key);
+ } catch (ImsException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public String getImsProvisioningString(int subId, int key) {
+ enforceReadPrivilegedPermission("getImsProvisioningString");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ return ImsManager.getInstance(mPhone.getContext(), getSlotIndexOrException(subId))
+ .getConfigInterface().getConfigString(key);
+ } catch (ImsException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public int setImsProvisioningInt(int subId, int key, int value) {
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
+ "setImsProvisioningInt");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ return ImsManager.getInstance(mPhone.getContext(), getSlotIndexOrException(subId))
+ .getConfigInterface().setConfig(key, value);
+ } catch (ImsException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public int setImsProvisioningString(int subId, int key, String value) {
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
+ "setImsProvisioningString");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
+ return ImsManager.getInstance(mPhone.getContext(), getSlotIndexOrException(subId))
+ .getConfigInterface().setConfig(key, value);
+ } catch (ImsException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
private int getSlotIndexOrException(int subId) throws IllegalArgumentException {
int slotId = SubscriptionManager.getSlotIndex(subId);
if (!SubscriptionManager.isValidSlotIndex(slotId)) {