diff options
| -rw-r--r-- | services/core/java/com/android/server/MmsServiceBroker.java | 166 |
1 files changed, 137 insertions, 29 deletions
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java index 0de6a03144b5..94096152670d 100644 --- a/services/core/java/com/android/server/MmsServiceBroker.java +++ b/services/core/java/com/android/server/MmsServiceBroker.java @@ -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(); + 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); } - // 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) { + // 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() { |