diff options
Diffstat (limited to 'src/android/support/v7/mms/MmsService.java')
-rw-r--r-- | src/android/support/v7/mms/MmsService.java | 465 |
1 files changed, 0 insertions, 465 deletions
diff --git a/src/android/support/v7/mms/MmsService.java b/src/android/support/v7/mms/MmsService.java deleted file mode 100644 index 650562f..0000000 --- a/src/android/support/v7/mms/MmsService.java +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (C) 2015 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.support.v7.mms; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.os.IBinder; -import android.os.PowerManager; -import android.os.Process; -import android.telephony.SmsManager; -import android.util.Log; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.RejectedExecutionException; - -/** - * Service to execute MMS requests using deprecated legacy APIs on older platform (prior to L) - */ -public class MmsService extends Service { - static final String TAG = "MmsLib"; - - //The default number of threads allowed to run MMS requests - private static final int DEFAULT_THREAD_POOL_SIZE = 4; - // Delay before stopping the service - private static final int SERVICE_STOP_DELAY_MILLIS = 2000; - - private static final String EXTRA_REQUEST = "request"; - private static final String EXTRA_MYPID = "mypid"; - - private static final String WAKELOCK_ID = "mmslib_wakelock"; - - /** - * Thread pool size for each request queue - */ - private static volatile int sThreadPoolSize = DEFAULT_THREAD_POOL_SIZE; - - /** - * Optional wake lock to use - */ - private static volatile boolean sUseWakeLock = true; - private static volatile PowerManager.WakeLock sWakeLock = null; - private static final Object sWakeLockLock = new Object(); - - /** - * Carrier configuration values loader - */ - private static volatile CarrierConfigValuesLoader sCarrierConfigValuesLoader = null; - - /** - * APN loader - */ - private static volatile ApnSettingsLoader sApnSettingsLoader = null; - - /** - * UserAgent and UA Prof URL loader - */ - private static volatile UserAgentInfoLoader sUserAgentInfoLoader = null; - - /** - * Set the size of thread pool for request execution. - * Default is DEFAULT_THREAD_POOL_SIZE - * - * @param size thread pool size - */ - static void setThreadPoolSize(final int size) { - sThreadPoolSize = size; - } - - /** - * Set whether to use wake lock - * - * @param useWakeLock true to use wake lock, false otherwise - */ - static void setUseWakeLock(final boolean useWakeLock) { - sUseWakeLock = useWakeLock; - } - - /** - * Set the optional carrier config values - * - * @param loader the carrier config values loader - */ - static void setCarrierConfigValuesLoader(final CarrierConfigValuesLoader loader) { - sCarrierConfigValuesLoader = loader; - } - - /** - * Get the current carrier config values loader - * - * @return the carrier config values loader currently set - */ - static CarrierConfigValuesLoader getCarrierConfigValuesLoader() { - return sCarrierConfigValuesLoader; - } - - /** - * Set APN settings loader - * - * @param loader the APN settings loader - */ - static void setApnSettingsLoader(final ApnSettingsLoader loader) { - sApnSettingsLoader = loader; - } - - /** - * Get the current APN settings loader - * - * @return the APN settings loader currently set - */ - static ApnSettingsLoader getApnSettingsLoader() { - return sApnSettingsLoader; - } - - /** - * Set user agent info loader - * - * @param loader the user agent info loader - */ - static void setUserAgentInfoLoader(final UserAgentInfoLoader loader) { - sUserAgentInfoLoader = loader; - } - - /** - * Get the current user agent info loader - * - * @return the user agent info loader currently set - */ - static UserAgentInfoLoader getUserAgentInfoLoader() { - return sUserAgentInfoLoader; - } - - /** - * Make sure loaders are not null. Set to default if that's the case - * - * @param context the Context to use - */ - private static void ensureLoaders(final Context context) { - if (sUserAgentInfoLoader == null) { - sUserAgentInfoLoader = new DefaultUserAgentInfoLoader(context); - } - if (sCarrierConfigValuesLoader == null) { - sCarrierConfigValuesLoader = new DefaultCarrierConfigValuesLoader(context); - } - if (sApnSettingsLoader == null) { - sApnSettingsLoader = new DefaultApnSettingsLoader(context); - } - } - - /** - * Acquire the wake lock - * - * @param context the context to use - */ - private static void acquireWakeLock(final Context context) { - synchronized (sWakeLockLock) { - if (sWakeLock == null) { - final PowerManager pm = - (PowerManager) context.getSystemService(Context.POWER_SERVICE); - sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_ID); - } - sWakeLock.acquire(); - } - } - - /** - * Release the wake lock - */ - private static void releaseWakeLock() { - boolean releasedEmptyWakeLock = false; - synchronized (sWakeLockLock) { - if (sWakeLock != null) { - sWakeLock.release(); - } else { - releasedEmptyWakeLock = true; - } - } - if (releasedEmptyWakeLock) { - Log.w(TAG, "Releasing empty wake lock"); - } - } - - /** - * Check if wake lock is not held (e.g. when service stops) - */ - private static void verifyWakeLockNotHeld() { - boolean wakeLockHeld = false; - synchronized (sWakeLockLock) { - wakeLockHeld = sWakeLock != null && sWakeLock.isHeld(); - } - if (wakeLockHeld) { - Log.e(TAG, "Wake lock still held!"); - } - } - - // Remember my PID to discard restarted intent - private static volatile int sMyPid = -1; - - /** - * Get the current PID - * - * @return the current PID - */ - private static int getMyPid() { - if (sMyPid < 0) { - sMyPid = Process.myPid(); - } - return sMyPid; - } - - /** - * Check if the intent is coming from this process - * - * @param intent the incoming intent for the service - * @return true if the intent is from the current process - */ - private static boolean fromThisProcess(final Intent intent) { - final int pid = intent.getIntExtra(EXTRA_MYPID, -1); - return pid == getMyPid(); - } - - // Request execution thread pools. One thread pool for sending and one for downloading. - // The size of the thread pool controls the parallelism of request execution. - // See {@link setThreadPoolSize} - private ExecutorService[] mExecutors = new ExecutorService[2]; - - // Active request count - private int mActiveRequestCount; - // The latest intent startId, used for safely stopping service - private int mLastStartId; - - private MmsNetworkManager mNetworkManager; - - // Handler for scheduling service stop - private final Handler mHandler = new Handler(); - // Service stop task - private final Runnable mServiceStopRunnable = new Runnable() { - @Override - public void run() { - tryStopService(); - } - }; - - /** - * Start the service with a request - * - * @param context the Context to use - * @param request the request to start - */ - public static void startRequest(final Context context, final MmsRequest request) { - final boolean useWakeLock = sUseWakeLock; - request.setUseWakeLock(useWakeLock); - final Intent intent = new Intent(context, MmsService.class); - intent.putExtra(EXTRA_REQUEST, request); - intent.putExtra(EXTRA_MYPID, getMyPid()); - if (useWakeLock) { - acquireWakeLock(context); - } - if (context.startService(intent) == null) { - if (useWakeLock) { - releaseWakeLock(); - } - } - } - - @Override - public void onCreate() { - super.onCreate(); - - ensureLoaders(this); - - for (int i = 0; i < mExecutors.length; i++) { - mExecutors[i] = Executors.newFixedThreadPool(sThreadPoolSize); - } - - mNetworkManager = new MmsNetworkManager(this); - - synchronized (this) { - mActiveRequestCount = 0; - mLastStartId = -1; - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - - for (ExecutorService executor : mExecutors) { - executor.shutdown(); - } - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - // Always remember the latest startId for use when we try releasing the service - synchronized (this) { - mLastStartId = startId; - } - boolean scheduled = false; - if (intent != null) { - // There is a rare situation that right after a intent is started, - // the service gets killed. Then the service will restart with - // the old intent which we don't want it to run since it will - // break our assumption for wake lock. Check the process ID - // embedded in the intent to make sure it is indeed from the - // the current life of this service. - if (fromThisProcess(intent)) { - final MmsRequest request = intent.getParcelableExtra(EXTRA_REQUEST); - if (request != null) { - try { - retainService(request, new Runnable() { - @Override - public void run() { - try { - request.execute( - MmsService.this, - mNetworkManager, - getApnSettingsLoader(), - getCarrierConfigValuesLoader(), - getUserAgentInfoLoader()); - } catch (Exception e) { - Log.w(TAG, "Unexpected execution failure", e); - } finally { - if (request.getUseWakeLock()) { - releaseWakeLock(); - } - releaseService(); - } - } - }); - scheduled = true; - } catch (RejectedExecutionException e) { - // Rare thing happened. Send back failure using the pending intent - // and also release the wake lock. - Log.w(TAG, "Executing request failed " + e); - request.returnResult(this, SmsManager.MMS_ERROR_UNSPECIFIED, - null/*response*/, 0/*httpStatusCode*/); - if (request.getUseWakeLock()) { - releaseWakeLock(); - } - } - } else { - Log.w(TAG, "Empty request"); - } - } else { - Log.w(TAG, "Got a restarted intent from previous incarnation"); - } - } else { - Log.w(TAG, "Empty intent"); - } - if (!scheduled) { - // If the request is not started successfully, we need to try shutdown the service - // if nobody is using it. - tryScheduleStop(); - } - return START_NOT_STICKY; - } - - /** - * Retain the service for executing the request in service thread pool - * - * @param request The request to execute - * @param runnable The runnable to run the request in thread pool - */ - private void retainService(final MmsRequest request, final Runnable runnable) { - final ExecutorService executor = getRequestExecutor(request); - synchronized (this) { - executor.execute(runnable); - mActiveRequestCount++; - } - } - - /** - * Release the service from the request. If nobody is using it, schedule service stop. - */ - private void releaseService() { - synchronized (this) { - mActiveRequestCount--; - if (mActiveRequestCount <= 0) { - mActiveRequestCount = 0; - rescheduleServiceStop(); - } - } - } - - /** - * Schedule the service stop if there is no active request - */ - private void tryScheduleStop() { - synchronized (this) { - if (mActiveRequestCount == 0) { - rescheduleServiceStop(); - } - } - } - - /** - * Reschedule service stop task - */ - private void rescheduleServiceStop() { - mHandler.removeCallbacks(mServiceStopRunnable); - mHandler.postDelayed(mServiceStopRunnable, SERVICE_STOP_DELAY_MILLIS); - } - - /** - * Really try to stop the service if there is not active request - */ - private void tryStopService() { - Boolean stopped = null; - synchronized (this) { - if (mActiveRequestCount == 0) { - stopped = stopSelfResult(mLastStartId); - } - } - logServiceStop(stopped); - } - - /** - * Log the result of service stopping. Also check wake lock status when service stops. - * - * @param stopped Not empty if service stop is performed: true if really stopped, false - * if cancelled. - */ - private void logServiceStop(final Boolean stopped) { - if (stopped != null) { - if (stopped) { - Log.i(TAG, "Service successfully stopped"); - verifyWakeLockNotHeld(); - } else { - Log.i(TAG, "Service stopping cancelled"); - } - } - } - - private ExecutorService getRequestExecutor(final MmsRequest request) { - if (request instanceof SendRequest) { - // Send - return mExecutors[0]; - } else { - // Download - return mExecutors[1]; - } - } - - @Override - public IBinder onBind(Intent intent) { - return null; - } -} |