Add support for async requestCellInfoUpdate
-Add support for asynchronous CellInfo update requests.
-Return cached CellInfo for Q+ callers of
getAllCellInfo().
-Naming cleanup to differentiate between
getAllCellInfo() and requestCellInfoUpdate().
Bug: 37100068
Bug: 63737292
Bug: 26569588
Test: manual (via SL4A)
Change-Id: I85f063d54c314e38e1d9521847f5c2c079eb3aeb
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 5401ddc..740a0d4 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;
@@ -217,6 +218,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 +1003,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 +1018,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 +1065,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 +1198,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 +1944,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 +1962,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 +1984,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());