Merge "Return pending intent to service caller if MmsService can't be connected"

This commit is contained in:
Ye Wen
2015-04-03 21:03:52 +00:00
committed by Android (Google) Code Review

View File

@@ -36,6 +36,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.service.carrier.CarrierMessagingService;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.util.Slog;
@@ -111,6 +112,106 @@ public class MmsServiceBroker extends SystemService {
}
};
// Instance of IMms for returning failure to service API caller,
// used when MmsService cannot be connected.
private final IMms mServiceStubForFailure = new IMms() {
@Override
public IBinder asBinder() {
return null;
}
@Override
public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl,
Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
returnPendingIntentWithError(sentIntent);
}
@Override
public void downloadMessage(int subId, String callingPkg, String locationUrl,
Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)
throws RemoteException {
returnPendingIntentWithError(downloadedIntent);
}
@Override
public Bundle getCarrierConfigValues(int subId) throws RemoteException {
return null;
}
@Override
public Uri importTextMessage(String callingPkg, String address, int type, String text,
long timestampMillis, boolean seen, boolean read) throws RemoteException {
return null;
}
@Override
public Uri importMultimediaMessage(String callingPkg, Uri contentUri, String messageId,
long timestampSecs, boolean seen, boolean read) throws RemoteException {
return null;
}
@Override
public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
throws RemoteException {
return false;
}
@Override
public boolean deleteStoredConversation(String callingPkg, long conversationId)
throws RemoteException {
return false;
}
@Override
public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
ContentValues statusValues) throws RemoteException {
return false;
}
@Override
public boolean archiveStoredConversation(String callingPkg, long conversationId,
boolean archived) throws RemoteException {
return false;
}
@Override
public Uri addTextMessageDraft(String callingPkg, String address, String text)
throws RemoteException {
return null;
}
@Override
public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
throws RemoteException {
return null;
}
@Override
public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
returnPendingIntentWithError(sentIntent);
}
@Override
public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
// Do nothing
}
@Override
public boolean getAutoPersisting() throws RemoteException {
return false;
}
private void returnPendingIntentWithError(PendingIntent pendingIntent) {
try {
pendingIntent.send(mContext, SmsManager.MMS_ERROR_UNSPECIFIED, null);
} catch (PendingIntent.CanceledException e) {
Slog.e(TAG, "Failed to return pending intent result", e);
}
}
};
public MmsServiceBroker(Context context) {
super(context);
mContext = context;
@@ -145,44 +246,51 @@ public class MmsServiceBroker extends SystemService {
}
}
private void ensureService() {
private IMms getOrConnectService() {
synchronized (this) {
if (mService == null) {
// Service is not connected. Try blocking connecting.
Slog.w(TAG, "MmsService not connected. Try connecting...");
mConnectionHandler.sendMessage(
mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
final long shouldEnd =
SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
while (waitTime > 0) {
try {
// TODO: consider using Java concurrent construct instead of raw object wait
this.wait(waitTime);
} catch (InterruptedException e) {
Slog.w(TAG, "Connection wait interrupted", e);
}
if (mService != null) {
// Success
return;
}
// Calculate remaining waiting time to make sure we wait the full timeout period
waitTime = shouldEnd - SystemClock.elapsedRealtime();
}
// Timed out. Something's really wrong.
Slog.e(TAG, "Can not connect to MmsService (timed out)");
throw new RuntimeException("Timed out in connecting to MmsService");
if (mService != null) {
return mService;
}
// Service is not connected. Try blocking connecting.
Slog.w(TAG, "MmsService not connected. Try connecting...");
mConnectionHandler.sendMessage(
mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
final long shouldEnd =
SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
while (waitTime > 0) {
try {
// TODO: consider using Java concurrent construct instead of raw object wait
this.wait(waitTime);
} catch (InterruptedException e) {
Slog.w(TAG, "Connection wait interrupted", e);
}
if (mService != null) {
// Success
return mService;
}
// Calculate remaining waiting time to make sure we wait the full timeout period
waitTime = shouldEnd - SystemClock.elapsedRealtime();
}
// Timed out. Something's really wrong.
Slog.e(TAG, "Can not connect to MmsService (timed out)");
return null;
}
}
/**
* Making sure when we obtain the mService instance it is always valid.
* Throws {@link RuntimeException} when it is empty.
* Make sure to return a non-empty service instance. Return the connected MmsService
* instance, if not connected, try connecting. If fail to connect, return a fake service
* instance which returns failure to service caller.
*
* @return a non-empty service instance, real or fake
*/
private IMms getServiceGuarded() {
ensureService();
return mService;
final IMms service = getOrConnectService();
if (service != null) {
return service;
}
return mServiceStubForFailure;
}
private AppOpsManager getAppOpsManager() {