summaryrefslogtreecommitdiffstats
path: root/src/android/support/v7/mms/MmsService.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/support/v7/mms/MmsService.java')
-rw-r--r--src/android/support/v7/mms/MmsService.java465
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;
- }
-}