EmailBroadcastProcessorService.java revision 31d9acbf0623872f9d4a2b3210b5970854b654c7
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.email.service; 18 19import com.android.email.Email; 20import com.android.email.ExchangeUtils; 21import com.android.email.Preferences; 22import com.android.email.SecurityPolicy; 23import com.android.email.VendorPolicyLoader; 24import com.android.email.activity.setup.AccountSettingsXL; 25import com.android.email.widget.WidgetManager; 26import com.android.emailcommon.Logging; 27 28import android.accounts.AccountManager; 29import android.app.IntentService; 30import android.content.ComponentName; 31import android.content.Context; 32import android.content.Intent; 33import android.content.pm.PackageManager; 34import android.util.Log; 35 36/** 37 * The service that really handles broadcast intents on a worker thread. 38 * 39 * We make it a service, because: 40 * <ul> 41 * <li>So that it's less likely for the process to get killed. 42 * <li>Even if it does, the Intent that have started it will be re-delivered by the system, 43 * and we can start the process again. (Using {@link #setIntentRedelivery}). 44 * </ul> 45 * 46 * This also handles the DeviceAdminReceiver in SecurityPolicy, because it is also 47 * a BroadcastReceiver and requires the same processing semantics. 48 */ 49public class EmailBroadcastProcessorService extends IntentService { 50 // Action used for BroadcastReceiver entry point 51 private static final String ACTION_BROADCAST = "broadcast_receiver"; 52 53 // Dialing "*#*#36245#*#*" to open the debug screen. "36245" = "email" 54 private static final String ACTION_SECRET_CODE = "android.provider.Telephony.SECRET_CODE"; 55 private static final String SECRET_CODE_HOST_DEBUG_SCREEN = "36245"; 56 57 // This is a helper used to process DeviceAdminReceiver messages 58 private static final String ACTION_DEVICE_POLICY_ADMIN = "com.android.email.devicepolicy"; 59 private static final String EXTRA_DEVICE_POLICY_ADMIN = "message_code"; 60 61 public EmailBroadcastProcessorService() { 62 // Class name will be the thread name. 63 super(EmailBroadcastProcessorService.class.getName()); 64 65 // Intent should be redelivered if the process gets killed before completing the job. 66 setIntentRedelivery(true); 67 } 68 69 /** 70 * Entry point for {@link EmailBroadcastReceiver}. 71 */ 72 public static void processBroadcastIntent(Context context, Intent broadcastIntent) { 73 Intent i = new Intent(context, EmailBroadcastProcessorService.class); 74 i.setAction(ACTION_BROADCAST); 75 i.putExtra(Intent.EXTRA_INTENT, broadcastIntent); 76 context.startService(i); 77 } 78 79 /** 80 * Entry point for {@link com.android.email.SecurityPolicy.PolicyAdmin}. These will 81 * simply callback to {@link 82 * com.android.email.SecurityPolicy#onDeviceAdminReceiverMessage(Context, int)}. 83 */ 84 public static void processDevicePolicyMessage(Context context, int message) { 85 Intent i = new Intent(context, EmailBroadcastProcessorService.class); 86 i.setAction(ACTION_DEVICE_POLICY_ADMIN); 87 i.putExtra(EXTRA_DEVICE_POLICY_ADMIN, message); 88 context.startService(i); 89 } 90 91 @Override 92 protected void onHandleIntent(Intent intent) { 93 // This method is called on a worker thread. 94 95 // Dispatch from entry point 96 final String action = intent.getAction(); 97 if (ACTION_BROADCAST.equals(action)) { 98 final Intent broadcastIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT); 99 final String broadcastAction = broadcastIntent.getAction(); 100 101 if (Intent.ACTION_BOOT_COMPLETED.equals(broadcastAction)) { 102 onBootCompleted(); 103 104 // TODO: Do a better job when we get ACTION_DEVICE_STORAGE_LOW. 105 // The code below came from very old code.... 106 } else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(broadcastAction)) { 107 // Stop IMAP/POP3 poll. 108 MailService.actionCancel(this); 109 } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(broadcastAction)) { 110 enableComponentsIfNecessary(); 111 } else if (ACTION_SECRET_CODE.equals(broadcastAction) 112 && SECRET_CODE_HOST_DEBUG_SCREEN.equals(broadcastIntent.getData().getHost())) { 113 AccountSettingsXL.actionSettingsWithDebug(this); 114 } else if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(broadcastAction)) { 115 onSystemAccountChanged(); 116 } 117 } else if (ACTION_DEVICE_POLICY_ADMIN.equals(action)) { 118 int message = intent.getIntExtra(EXTRA_DEVICE_POLICY_ADMIN, -1); 119 SecurityPolicy.onDeviceAdminReceiverMessage(this, message); 120 } 121 } 122 123 private void enableComponentsIfNecessary() { 124 if (Email.setServicesEnabledSync(this)) { 125 // At least one account exists. 126 // TODO probably we should check if it's a POP/IMAP account. 127 MailService.actionReschedule(this); 128 } 129 } 130 131 /** 132 * Handles {@link Intent#ACTION_BOOT_COMPLETED}. Called on a worker thread. 133 */ 134 private void onBootCompleted() { 135 performOneTimeInitialization(); 136 137 enableComponentsIfNecessary(); 138 139 // Starts the service for Exchange, if supported. 140 ExchangeUtils.startExchangeService(this); 141 } 142 143 private void performOneTimeInitialization() { 144 final Preferences pref = Preferences.getPreferences(this); 145 int progress = pref.getOneTimeInitializationProgress(); 146 final int initialProgress = progress; 147 148 if (progress < 1) { 149 Log.i(Logging.LOG_TAG, "Onetime initialization: 1"); 150 progress = 1; 151 if (VendorPolicyLoader.getInstance(this).useAlternateExchangeStrings()) { 152 setComponentEnabled(EasAuthenticatorServiceAlternate.class, true); 153 setComponentEnabled(EasAuthenticatorService.class, false); 154 } 155 156 ExchangeUtils.enableEasCalendarSync(this); 157 } 158 159 // Add your initialization steps here. 160 // Use "progress" to skip the initializations that's already done before. 161 // Using this preference also makes it safe when a user skips an upgrade. (i.e. upgrading 162 // version N to version N+2) 163 164 if (progress != initialProgress) { 165 pref.setOneTimeInitializationProgress(progress); 166 Log.i(Logging.LOG_TAG, "Onetime initialization: completed."); 167 } 168 } 169 170 private void setComponentEnabled(Class<?> clazz, boolean enabled) { 171 final ComponentName c = new ComponentName(this, clazz.getName()); 172 getPackageManager().setComponentEnabledSetting(c, 173 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 174 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 175 PackageManager.DONT_KILL_APP); 176 } 177 178 private void onSystemAccountChanged() { 179 Log.i(Logging.LOG_TAG, "System accouns updated."); 180 MailService.reconcilePopImapAccountsSync(this); 181 182 // Let ExchangeService reconcile EAS accouts. 183 // The service will stops itself it there's no EAS accounts. 184 ExchangeUtils.startExchangeService(this); 185 186 // Let all of the widgets update 187 WidgetManager.getInstance().updateAllWidgets(); 188 } 189} 190