summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/BugleApplication.java
diff options
context:
space:
mode:
authorMike Dodd <mdodd@google.com>2015-08-11 11:16:59 -0700
committerMike Dodd <mdodd@google.com>2015-08-12 08:58:28 -0700
commit461a34b466cb4b13dbbc2ec6330b31e217b2ac4e (patch)
treebc4b489af52d0e2521e21167d2ad76a47256f348 /src/com/android/messaging/BugleApplication.java
parent8b3e2b9c1b0a09423a7ba5d1091b9192106502f8 (diff)
downloadandroid_packages_apps_Messaging-461a34b466cb4b13dbbc2ec6330b31e217b2ac4e.tar.gz
android_packages_apps_Messaging-461a34b466cb4b13dbbc2ec6330b31e217b2ac4e.tar.bz2
android_packages_apps_Messaging-461a34b466cb4b13dbbc2ec6330b31e217b2ac4e.zip
Initial checkin of AOSP Messaging app.
b/23110861 Change-Id: I9aa980d7569247d6b2ca78f5dcb4502e1eaadb8a
Diffstat (limited to 'src/com/android/messaging/BugleApplication.java')
-rw-r--r--src/com/android/messaging/BugleApplication.java262
1 files changed, 262 insertions, 0 deletions
diff --git a/src/com/android/messaging/BugleApplication.java b/src/com/android/messaging/BugleApplication.java
new file mode 100644
index 0000000..a5aea9f
--- /dev/null
+++ b/src/com/android/messaging/BugleApplication.java
@@ -0,0 +1,262 @@
+/*
+ * 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 com.android.messaging;
+
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.v7.mms.CarrierConfigValuesLoader;
+import android.support.v7.mms.MmsManager;
+import android.telephony.CarrierConfigManager;
+
+import com.android.messaging.datamodel.DataModel;
+import com.android.messaging.receiver.SmsReceiver;
+import com.android.messaging.sms.ApnDatabase;
+import com.android.messaging.sms.BugleApnSettingsLoader;
+import com.android.messaging.sms.BugleUserAgentInfoLoader;
+import com.android.messaging.sms.MmsConfig;
+import com.android.messaging.ui.ConversationDrawables;
+import com.android.messaging.util.BugleGservices;
+import com.android.messaging.util.BugleGservicesKeys;
+import com.android.messaging.util.BuglePrefs;
+import com.android.messaging.util.BuglePrefsKeys;
+import com.android.messaging.util.DebugUtils;
+import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.OsUtil;
+import com.android.messaging.util.PhoneUtils;
+import com.android.messaging.util.Trace;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.lang.Thread.UncaughtExceptionHandler;
+
+/**
+ * The application object
+ */
+public class BugleApplication extends Application implements UncaughtExceptionHandler {
+ private static final String TAG = LogUtil.BUGLE_TAG;
+
+ private UncaughtExceptionHandler sSystemUncaughtExceptionHandler;
+ private static boolean sRunningTests = false;
+
+ @VisibleForTesting
+ protected static void setTestsRunning() {
+ sRunningTests = true;
+ }
+
+ /**
+ * @return true if we're running unit tests.
+ */
+ public static boolean isRunningTests() {
+ return sRunningTests;
+ }
+
+ @Override
+ public void onCreate() {
+ Trace.beginSection("app.onCreate");
+ super.onCreate();
+
+ // Note onCreate is called in both test and real application environments
+ if (!sRunningTests) {
+ // Only create the factory if not running tests
+ FactoryImpl.register(getApplicationContext(), this);
+ } else {
+ LogUtil.e(TAG, "BugleApplication.onCreate: FactoryImpl.register skipped for test run");
+ }
+
+ sSystemUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
+ Thread.setDefaultUncaughtExceptionHandler(this);
+ Trace.endSection();
+ }
+
+ @Override
+ public void onConfigurationChanged(final Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ // Update conversation drawables when changing writing systems
+ // (Right-To-Left / Left-To-Right)
+ ConversationDrawables.get().updateDrawables();
+ }
+
+ // Called by the "real" factory from FactoryImpl.register() (i.e. not run in tests)
+ public void initializeSync(final Factory factory) {
+ Trace.beginSection("app.initializeSync");
+ final Context context = factory.getApplicationContext();
+ final BugleGservices bugleGservices = factory.getBugleGservices();
+ final BuglePrefs buglePrefs = factory.getApplicationPrefs();
+ final DataModel dataModel = factory.getDataModel();
+ final CarrierConfigValuesLoader carrierConfigValuesLoader =
+ factory.getCarrierConfigValuesLoader();
+
+ maybeStartProfiling();
+
+ BugleApplication.updateAppConfig(context);
+
+ // Initialize MMS lib
+ initMmsLib(context, bugleGservices, carrierConfigValuesLoader);
+ // Initialize APN database
+ ApnDatabase.initializeAppContext(context);
+ // Fixup messages in flight if we crashed and send any pending
+ dataModel.onApplicationCreated();
+ // Register carrier config change receiver
+ if (OsUtil.isAtLeastM()) {
+ registerCarrierConfigChangeReceiver(context);
+ }
+
+ Trace.endSection();
+ }
+
+ private static void registerCarrierConfigChangeReceiver(final Context context) {
+ context.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ LogUtil.i(TAG, "Carrier config changed. Reloading MMS config.");
+ MmsConfig.loadAsync();
+ }
+ }, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+ }
+
+ private static void initMmsLib(final Context context, final BugleGservices bugleGservices,
+ final CarrierConfigValuesLoader carrierConfigValuesLoader) {
+ MmsManager.setApnSettingsLoader(new BugleApnSettingsLoader(context));
+ MmsManager.setCarrierConfigValuesLoader(carrierConfigValuesLoader);
+ MmsManager.setUserAgentInfoLoader(new BugleUserAgentInfoLoader(context));
+ MmsManager.setUseWakeLock(true);
+ // If Gservices is configured not to use mms api, force MmsManager to always use
+ // legacy mms sending logic
+ MmsManager.setForceLegacyMms(!bugleGservices.getBoolean(
+ BugleGservicesKeys.USE_MMS_API_IF_PRESENT,
+ BugleGservicesKeys.USE_MMS_API_IF_PRESENT_DEFAULT));
+ bugleGservices.registerForChanges(new Runnable() {
+ @Override
+ public void run() {
+ MmsManager.setForceLegacyMms(!bugleGservices.getBoolean(
+ BugleGservicesKeys.USE_MMS_API_IF_PRESENT,
+ BugleGservicesKeys.USE_MMS_API_IF_PRESENT_DEFAULT));
+ }
+ });
+ }
+
+ public static void updateAppConfig(final Context context) {
+ // Make sure we set the correct state for the SMS/MMS receivers
+ SmsReceiver.updateSmsReceiveHandler(context);
+ }
+
+ // Called from thread started in FactoryImpl.register() (i.e. not run in tests)
+ public void initializeAsync(final Factory factory) {
+ // Handle shared prefs upgrade & Load MMS Configuration
+ Trace.beginSection("app.initializeAsync");
+ maybeHandleSharedPrefsUpgrade(factory);
+ MmsConfig.load();
+ Trace.endSection();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+
+ if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
+ LogUtil.d(TAG, "BugleApplication.onLowMemory");
+ }
+ Factory.get().reclaimMemory();
+ }
+
+ @Override
+ public void uncaughtException(final Thread thread, final Throwable ex) {
+ final boolean background = getMainLooper().getThread() != thread;
+ if (background) {
+ LogUtil.e(TAG, "Uncaught exception in background thread " + thread, ex);
+
+ final Handler handler = new Handler(getMainLooper());
+ handler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ sSystemUncaughtExceptionHandler.uncaughtException(thread, ex);
+ }
+ });
+ } else {
+ sSystemUncaughtExceptionHandler.uncaughtException(thread, ex);
+ }
+ }
+
+ private void maybeStartProfiling() {
+ // App startup profiling support. To use it:
+ // adb shell setprop log.tag.BugleProfile DEBUG
+ // # Start the app, wait for a 30s, download trace file:
+ // adb pull /data/data/com.android.messaging/cache/startup.trace /tmp
+ // # Open trace file (using adt/tools/traceview)
+ if (android.util.Log.isLoggable(LogUtil.PROFILE_TAG, android.util.Log.DEBUG)) {
+ // Start method tracing with a big enough buffer and let it run for 30s.
+ // Note we use a logging tag as we don't want to wait for gservices to start up.
+ final File file = DebugUtils.getDebugFile("startup.trace", true);
+ if (file != null) {
+ android.os.Debug.startMethodTracing(file.getAbsolutePath(), 160 * 1024 * 1024);
+ new Handler(Looper.getMainLooper()).postDelayed(
+ new Runnable() {
+ @Override
+ public void run() {
+ android.os.Debug.stopMethodTracing();
+ // Allow world to see trace file
+ DebugUtils.ensureReadable(file);
+ LogUtil.d(LogUtil.PROFILE_TAG, "Tracing complete - "
+ + file.getAbsolutePath());
+ }
+ }, 30000);
+ }
+ }
+ }
+
+ private void maybeHandleSharedPrefsUpgrade(final Factory factory) {
+ final int existingVersion = factory.getApplicationPrefs().getInt(
+ BuglePrefsKeys.SHARED_PREFERENCES_VERSION,
+ BuglePrefsKeys.SHARED_PREFERENCES_VERSION_DEFAULT);
+ final int targetVersion = Integer.parseInt(getString(R.string.pref_version));
+ if (targetVersion > existingVersion) {
+ LogUtil.i(LogUtil.BUGLE_TAG, "Upgrading shared prefs from " + existingVersion +
+ " to " + targetVersion);
+ try {
+ // Perform upgrade on application-wide prefs.
+ factory.getApplicationPrefs().onUpgrade(existingVersion, targetVersion);
+ // Perform upgrade on each subscription's prefs.
+ PhoneUtils.forEachActiveSubscription(new PhoneUtils.SubscriptionRunnable() {
+ @Override
+ public void runForSubscription(final int subId) {
+ factory.getSubscriptionPrefs(subId)
+ .onUpgrade(existingVersion, targetVersion);
+ }
+ });
+ factory.getApplicationPrefs().putInt(BuglePrefsKeys.SHARED_PREFERENCES_VERSION,
+ targetVersion);
+ } catch (final Exception ex) {
+ // Upgrade failed. Don't crash the app because we can always fall back to the
+ // default settings.
+ LogUtil.e(LogUtil.BUGLE_TAG, "Failed to upgrade shared prefs", ex);
+ }
+ } else if (targetVersion < existingVersion) {
+ // We don't care about downgrade since real user shouldn't encounter this, so log it
+ // and ignore any prefs migration.
+ LogUtil.e(LogUtil.BUGLE_TAG, "Shared prefs downgrade requested and ignored. " +
+ "oldVersion = " + existingVersion + ", newVersion = " + targetVersion);
+ }
+ }
+}