2010-05-28 01:29:35 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 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.email.service;
|
|
|
|
|
2011-01-14 20:00:17 +00:00
|
|
|
import android.accounts.AccountManager;
|
2010-05-28 01:29:35 +00:00
|
|
|
import android.app.IntentService;
|
|
|
|
import android.content.ComponentName;
|
2011-02-22 22:17:37 +00:00
|
|
|
import android.content.ContentResolver;
|
|
|
|
import android.content.ContentUris;
|
|
|
|
import android.content.ContentValues;
|
2010-05-28 01:29:35 +00:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
2013-07-25 00:00:35 +00:00
|
|
|
import android.content.PeriodicSync;
|
2010-05-28 01:29:35 +00:00
|
|
|
import android.content.pm.PackageManager;
|
2011-02-22 22:17:37 +00:00
|
|
|
import android.database.Cursor;
|
|
|
|
import android.net.Uri;
|
2013-07-25 00:00:35 +00:00
|
|
|
import android.os.Bundle;
|
|
|
|
import android.provider.CalendarContract;
|
|
|
|
import android.provider.ContactsContract;
|
|
|
|
import android.text.format.DateUtils;
|
2010-05-28 01:29:35 +00:00
|
|
|
|
2011-06-27 19:12:41 +00:00
|
|
|
import com.android.email.Preferences;
|
2012-09-20 20:34:13 +00:00
|
|
|
import com.android.email.R;
|
2011-06-27 19:12:41 +00:00
|
|
|
import com.android.email.SecurityPolicy;
|
|
|
|
import com.android.email.activity.setup.AccountSettings;
|
2013-07-26 21:18:39 +00:00
|
|
|
import com.android.email.provider.AccountReconciler;
|
2011-06-27 19:12:41 +00:00
|
|
|
import com.android.emailcommon.Logging;
|
2012-06-29 16:42:05 +00:00
|
|
|
import com.android.emailcommon.VendorPolicyLoader;
|
2011-06-27 19:12:41 +00:00
|
|
|
import com.android.emailcommon.provider.Account;
|
2013-07-25 00:00:35 +00:00
|
|
|
import com.android.emailcommon.provider.EmailContent;
|
2011-06-27 19:12:41 +00:00
|
|
|
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
|
|
|
import com.android.emailcommon.provider.HostAuth;
|
2013-05-26 04:32:32 +00:00
|
|
|
import com.android.mail.utils.LogUtils;
|
2013-07-25 00:00:35 +00:00
|
|
|
import com.google.common.collect.Maps;
|
2011-06-27 19:12:41 +00:00
|
|
|
|
2013-07-25 00:00:35 +00:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
2013-07-22 22:26:34 +00:00
|
|
|
|
2010-05-28 01:29:35 +00:00
|
|
|
/**
|
|
|
|
* The service that really handles broadcast intents on a worker thread.
|
|
|
|
*
|
|
|
|
* We make it a service, because:
|
|
|
|
* <ul>
|
|
|
|
* <li>So that it's less likely for the process to get killed.
|
|
|
|
* <li>Even if it does, the Intent that have started it will be re-delivered by the system,
|
|
|
|
* and we can start the process again. (Using {@link #setIntentRedelivery}).
|
|
|
|
* </ul>
|
2010-12-30 08:16:55 +00:00
|
|
|
*
|
|
|
|
* This also handles the DeviceAdminReceiver in SecurityPolicy, because it is also
|
|
|
|
* a BroadcastReceiver and requires the same processing semantics.
|
2010-05-28 01:29:35 +00:00
|
|
|
*/
|
|
|
|
public class EmailBroadcastProcessorService extends IntentService {
|
2010-12-30 08:16:55 +00:00
|
|
|
// Action used for BroadcastReceiver entry point
|
|
|
|
private static final String ACTION_BROADCAST = "broadcast_receiver";
|
|
|
|
|
2010-06-30 22:43:12 +00:00
|
|
|
// Dialing "*#*#36245#*#*" to open the debug screen. "36245" = "email"
|
2010-12-30 08:16:55 +00:00
|
|
|
private static final String ACTION_SECRET_CODE = "android.provider.Telephony.SECRET_CODE";
|
2010-06-30 22:43:12 +00:00
|
|
|
private static final String SECRET_CODE_HOST_DEBUG_SCREEN = "36245";
|
|
|
|
|
2010-12-30 08:16:55 +00:00
|
|
|
// This is a helper used to process DeviceAdminReceiver messages
|
|
|
|
private static final String ACTION_DEVICE_POLICY_ADMIN = "com.android.email.devicepolicy";
|
|
|
|
private static final String EXTRA_DEVICE_POLICY_ADMIN = "message_code";
|
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
// Action used for EmailUpgradeBroadcastReceiver.
|
|
|
|
private static final String ACTION_UPGRADE_BROADCAST = "upgrade_broadcast_receiver";
|
|
|
|
|
2010-05-28 01:29:35 +00:00
|
|
|
public EmailBroadcastProcessorService() {
|
|
|
|
// Class name will be the thread name.
|
|
|
|
super(EmailBroadcastProcessorService.class.getName());
|
|
|
|
|
|
|
|
// Intent should be redelivered if the process gets killed before completing the job.
|
|
|
|
setIntentRedelivery(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Entry point for {@link EmailBroadcastReceiver}.
|
|
|
|
*/
|
|
|
|
public static void processBroadcastIntent(Context context, Intent broadcastIntent) {
|
|
|
|
Intent i = new Intent(context, EmailBroadcastProcessorService.class);
|
2010-12-30 08:16:55 +00:00
|
|
|
i.setAction(ACTION_BROADCAST);
|
2010-05-28 01:29:35 +00:00
|
|
|
i.putExtra(Intent.EXTRA_INTENT, broadcastIntent);
|
|
|
|
context.startService(i);
|
|
|
|
}
|
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
public static void processUpgradeBroadcastIntent(final Context context) {
|
|
|
|
final Intent i = new Intent(context, EmailBroadcastProcessorService.class);
|
|
|
|
i.setAction(ACTION_UPGRADE_BROADCAST);
|
|
|
|
context.startService(i);
|
|
|
|
}
|
|
|
|
|
2010-12-30 08:16:55 +00:00
|
|
|
/**
|
|
|
|
* Entry point for {@link com.android.email.SecurityPolicy.PolicyAdmin}. These will
|
|
|
|
* simply callback to {@link
|
|
|
|
* com.android.email.SecurityPolicy#onDeviceAdminReceiverMessage(Context, int)}.
|
|
|
|
*/
|
|
|
|
public static void processDevicePolicyMessage(Context context, int message) {
|
|
|
|
Intent i = new Intent(context, EmailBroadcastProcessorService.class);
|
|
|
|
i.setAction(ACTION_DEVICE_POLICY_ADMIN);
|
|
|
|
i.putExtra(EXTRA_DEVICE_POLICY_ADMIN, message);
|
|
|
|
context.startService(i);
|
|
|
|
}
|
|
|
|
|
2010-05-28 01:29:35 +00:00
|
|
|
@Override
|
|
|
|
protected void onHandleIntent(Intent intent) {
|
|
|
|
// This method is called on a worker thread.
|
|
|
|
|
2010-12-30 08:16:55 +00:00
|
|
|
// Dispatch from entry point
|
|
|
|
final String action = intent.getAction();
|
|
|
|
if (ACTION_BROADCAST.equals(action)) {
|
|
|
|
final Intent broadcastIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT);
|
|
|
|
final String broadcastAction = broadcastIntent.getAction();
|
2010-05-28 01:29:35 +00:00
|
|
|
|
2010-12-30 08:16:55 +00:00
|
|
|
if (Intent.ACTION_BOOT_COMPLETED.equals(broadcastAction)) {
|
|
|
|
onBootCompleted();
|
2012-04-25 17:26:46 +00:00
|
|
|
} else if (ACTION_SECRET_CODE.equals(broadcastAction)
|
2010-12-30 08:16:55 +00:00
|
|
|
&& SECRET_CODE_HOST_DEBUG_SCREEN.equals(broadcastIntent.getData().getHost())) {
|
2011-05-13 00:27:56 +00:00
|
|
|
AccountSettings.actionSettingsWithDebug(this);
|
2011-01-14 20:00:17 +00:00
|
|
|
} else if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(broadcastAction)) {
|
|
|
|
onSystemAccountChanged();
|
2010-12-30 08:16:55 +00:00
|
|
|
}
|
|
|
|
} else if (ACTION_DEVICE_POLICY_ADMIN.equals(action)) {
|
|
|
|
int message = intent.getIntExtra(EXTRA_DEVICE_POLICY_ADMIN, -1);
|
|
|
|
SecurityPolicy.onDeviceAdminReceiverMessage(this, message);
|
2013-07-22 22:26:34 +00:00
|
|
|
} else if (ACTION_UPGRADE_BROADCAST.equals(action)) {
|
|
|
|
onAppUpgrade();
|
2010-05-28 01:29:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
private void disableComponent(final Class<?> klass) {
|
|
|
|
getPackageManager().setComponentEnabledSetting(new ComponentName(this, klass),
|
|
|
|
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
|
|
|
|
}
|
|
|
|
|
2013-10-16 22:57:25 +00:00
|
|
|
private boolean isComponentDisabled(final Class<?> klass) {
|
|
|
|
return getPackageManager().getComponentEnabledSetting(new ComponentName(this, klass))
|
|
|
|
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
|
|
|
|
}
|
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
private void updateAccountManagerAccountsOfType(final String amAccountType,
|
2013-07-25 00:00:35 +00:00
|
|
|
final Map<String, String> protocolMap) {
|
2013-07-22 22:26:34 +00:00
|
|
|
final android.accounts.Account[] amAccounts =
|
|
|
|
AccountManager.get(this).getAccountsByType(amAccountType);
|
|
|
|
|
|
|
|
for (android.accounts.Account amAccount: amAccounts) {
|
|
|
|
EmailServiceUtils.updateAccountManagerType(this, amAccount, protocolMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-25 00:00:35 +00:00
|
|
|
/**
|
|
|
|
* Delete all periodic syncs for an account.
|
|
|
|
* @param amAccount The account for which to disable syncs.
|
|
|
|
* @param authority The authority for which to disable syncs.
|
|
|
|
*/
|
2013-08-01 15:47:51 +00:00
|
|
|
private static void removePeriodicSyncs(final android.accounts.Account amAccount,
|
2013-07-25 00:00:35 +00:00
|
|
|
final String authority) {
|
|
|
|
final List<PeriodicSync> syncs =
|
|
|
|
ContentResolver.getPeriodicSyncs(amAccount, authority);
|
|
|
|
for (final PeriodicSync sync : syncs) {
|
|
|
|
ContentResolver.removePeriodicSync(amAccount, authority, sync.extras);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove all existing periodic syncs for an account type, and add the necessary syncs.
|
|
|
|
* @param amAccountType The account type to handle.
|
|
|
|
* @param syncIntervals The map of all account addresses to sync intervals in the DB.
|
|
|
|
*/
|
|
|
|
private void fixPeriodicSyncs(final String amAccountType,
|
|
|
|
final Map<String, Integer> syncIntervals) {
|
|
|
|
final android.accounts.Account[] amAccounts =
|
|
|
|
AccountManager.get(this).getAccountsByType(amAccountType);
|
|
|
|
for (android.accounts.Account amAccount : amAccounts) {
|
|
|
|
// First delete existing periodic syncs.
|
|
|
|
removePeriodicSyncs(amAccount, EmailContent.AUTHORITY);
|
|
|
|
removePeriodicSyncs(amAccount, CalendarContract.AUTHORITY);
|
|
|
|
removePeriodicSyncs(amAccount, ContactsContract.AUTHORITY);
|
|
|
|
|
|
|
|
// Add back a sync for this account if necessary (i.e. the account has a positive
|
|
|
|
// sync interval in the DB). This assumes that the email app requires unique email
|
|
|
|
// addresses for each account, which is currently the case.
|
|
|
|
final Integer syncInterval = syncIntervals.get(amAccount.name);
|
|
|
|
if (syncInterval != null && syncInterval > 0) {
|
|
|
|
// Sync interval is stored in minutes in DB, but we want the value in seconds.
|
|
|
|
ContentResolver.addPeriodicSync(amAccount, EmailContent.AUTHORITY, Bundle.EMPTY,
|
|
|
|
syncInterval * DateUtils.MINUTE_IN_MILLIS / DateUtils.SECOND_IN_MILLIS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Projection used for getting sync intervals for all accounts. */
|
|
|
|
private static final String[] ACCOUNT_SYNC_INTERVAL_PROJECTION =
|
|
|
|
{ AccountColumns.EMAIL_ADDRESS, AccountColumns.SYNC_INTERVAL };
|
|
|
|
private static final int ACCOUNT_SYNC_INTERVAL_ADDRESS_COLUMN = 0;
|
|
|
|
private static final int ACCOUNT_SYNC_INTERVAL_INTERVAL_COLUMN = 1;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the sync interval for all accounts, as stored in the DB.
|
|
|
|
* @return The map of all sync intervals by account email address.
|
|
|
|
*/
|
|
|
|
private Map<String, Integer> getSyncIntervals() {
|
|
|
|
final Cursor c = getContentResolver().query(Account.CONTENT_URI,
|
|
|
|
ACCOUNT_SYNC_INTERVAL_PROJECTION, null, null, null);
|
|
|
|
if (c != null) {
|
|
|
|
final Map<String, Integer> periodicSyncs =
|
|
|
|
Maps.newHashMapWithExpectedSize(c.getCount());
|
|
|
|
try {
|
|
|
|
while (c.moveToNext()) {
|
|
|
|
periodicSyncs.put(c.getString(ACCOUNT_SYNC_INTERVAL_ADDRESS_COLUMN),
|
|
|
|
c.getInt(ACCOUNT_SYNC_INTERVAL_INTERVAL_COLUMN));
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
return periodicSyncs;
|
|
|
|
}
|
|
|
|
return Collections.emptyMap();
|
|
|
|
}
|
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
private void onAppUpgrade() {
|
2013-10-16 22:57:25 +00:00
|
|
|
if (isComponentDisabled(EmailUpgradeBroadcastReceiver.class)) {
|
|
|
|
return;
|
|
|
|
}
|
2013-07-22 22:26:34 +00:00
|
|
|
// TODO: Only do this for Email2Google.
|
|
|
|
// When upgrading to Email2Google, we need to essentially rename the account manager
|
|
|
|
// type for all existing accounts, so we add new ones and delete the old.
|
|
|
|
// We specify the translations in this map. We map from old protocol name to new protocol
|
|
|
|
// name, and from protocol name + "_type" to new account manager type name. (Email1 did
|
|
|
|
// not use distinct account manager types for POP and IMAP, but Email2 does, hence this
|
|
|
|
// weird mapping.)
|
2013-07-25 00:00:35 +00:00
|
|
|
final Map<String, String> protocolMap = Maps.newHashMapWithExpectedSize(4);
|
2013-07-22 22:26:34 +00:00
|
|
|
protocolMap.put("imap", getString(R.string.protocol_legacy_imap));
|
|
|
|
protocolMap.put("pop3", getString(R.string.protocol_pop3));
|
|
|
|
protocolMap.put("imap_type", getString(R.string.account_manager_type_legacy_imap));
|
|
|
|
protocolMap.put("pop3_type", getString(R.string.account_manager_type_pop3));
|
|
|
|
updateAccountManagerAccountsOfType("com.android.email", protocolMap);
|
|
|
|
|
|
|
|
protocolMap.clear();
|
|
|
|
protocolMap.put("eas", getString(R.string.protocol_eas));
|
|
|
|
protocolMap.put("eas_type", getString(R.string.account_manager_type_exchange));
|
|
|
|
updateAccountManagerAccountsOfType("com.android.exchange", protocolMap);
|
|
|
|
|
|
|
|
// Disable the old authenticators.
|
|
|
|
disableComponent(LegacyEmailAuthenticatorService.class);
|
|
|
|
disableComponent(LegacyEasAuthenticatorService.class);
|
|
|
|
|
2013-07-25 00:00:35 +00:00
|
|
|
// Fix periodic syncs.
|
|
|
|
final Map<String, Integer> syncIntervals = getSyncIntervals();
|
2013-08-09 18:50:48 +00:00
|
|
|
for (final EmailServiceUtils.EmailServiceInfo service
|
|
|
|
: EmailServiceUtils.getServiceInfoList(this)) {
|
2013-07-25 00:00:35 +00:00
|
|
|
fixPeriodicSyncs(service.accountType, syncIntervals);
|
|
|
|
}
|
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
// Disable the upgrade broadcast receiver now that we're fully upgraded.
|
|
|
|
disableComponent(EmailUpgradeBroadcastReceiver.class);
|
|
|
|
}
|
|
|
|
|
2010-05-28 01:29:35 +00:00
|
|
|
/**
|
|
|
|
* Handles {@link Intent#ACTION_BOOT_COMPLETED}. Called on a worker thread.
|
|
|
|
*/
|
|
|
|
private void onBootCompleted() {
|
|
|
|
performOneTimeInitialization();
|
2012-09-03 18:46:10 +00:00
|
|
|
reconcileAndStartServices();
|
|
|
|
}
|
2010-05-28 01:29:35 +00:00
|
|
|
|
2012-09-03 18:46:10 +00:00
|
|
|
private void reconcileAndStartServices() {
|
2013-10-16 22:57:25 +00:00
|
|
|
/**
|
|
|
|
* We can get here before the ACTION_UPGRADE_BROADCAST is received, so make sure the
|
|
|
|
* accounts are converted otherwise terrible, horrible things will happen.
|
|
|
|
*/
|
|
|
|
onAppUpgrade();
|
2012-09-03 18:46:10 +00:00
|
|
|
// Reconcile accounts
|
2013-07-26 21:18:39 +00:00
|
|
|
AccountReconciler.reconcileAccounts(this);
|
2012-06-28 17:40:46 +00:00
|
|
|
// Starts remote services, if any
|
|
|
|
EmailServiceUtils.startRemoteServices(this);
|
2010-05-28 01:29:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void performOneTimeInitialization() {
|
|
|
|
final Preferences pref = Preferences.getPreferences(this);
|
|
|
|
int progress = pref.getOneTimeInitializationProgress();
|
|
|
|
final int initialProgress = progress;
|
|
|
|
|
|
|
|
if (progress < 1) {
|
2013-05-26 04:32:32 +00:00
|
|
|
LogUtils.i(Logging.LOG_TAG, "Onetime initialization: 1");
|
2010-05-28 01:29:35 +00:00
|
|
|
progress = 1;
|
|
|
|
if (VendorPolicyLoader.getInstance(this).useAlternateExchangeStrings()) {
|
|
|
|
setComponentEnabled(EasAuthenticatorServiceAlternate.class, true);
|
|
|
|
setComponentEnabled(EasAuthenticatorService.class, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-22 22:17:37 +00:00
|
|
|
if (progress < 2) {
|
2013-05-26 04:32:32 +00:00
|
|
|
LogUtils.i(Logging.LOG_TAG, "Onetime initialization: 2");
|
2011-02-22 22:17:37 +00:00
|
|
|
progress = 2;
|
|
|
|
setImapDeletePolicy(this);
|
|
|
|
}
|
|
|
|
|
2010-05-28 01:29:35 +00:00
|
|
|
// Add your initialization steps here.
|
|
|
|
// Use "progress" to skip the initializations that's already done before.
|
|
|
|
// Using this preference also makes it safe when a user skips an upgrade. (i.e. upgrading
|
|
|
|
// version N to version N+2)
|
|
|
|
|
|
|
|
if (progress != initialProgress) {
|
|
|
|
pref.setOneTimeInitializationProgress(progress);
|
2013-05-26 04:32:32 +00:00
|
|
|
LogUtils.i(Logging.LOG_TAG, "Onetime initialization: completed.");
|
2010-05-28 01:29:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-22 22:17:37 +00:00
|
|
|
/**
|
|
|
|
* Sets the delete policy to the correct value for all IMAP accounts. This will have no
|
|
|
|
* effect on either EAS or POP3 accounts.
|
|
|
|
*/
|
|
|
|
/*package*/ static void setImapDeletePolicy(Context context) {
|
|
|
|
ContentResolver resolver = context.getContentResolver();
|
|
|
|
Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
try {
|
|
|
|
while (c.moveToNext()) {
|
|
|
|
long recvAuthKey = c.getLong(Account.CONTENT_HOST_AUTH_KEY_RECV_COLUMN);
|
|
|
|
HostAuth recvAuth = HostAuth.restoreHostAuthWithId(context, recvAuthKey);
|
2012-09-20 20:34:13 +00:00
|
|
|
String legacyImapProtocol = context.getString(R.string.protocol_legacy_imap);
|
|
|
|
if (legacyImapProtocol.equals(recvAuth.mProtocol)) {
|
2011-02-22 22:17:37 +00:00
|
|
|
int flags = c.getInt(Account.CONTENT_FLAGS_COLUMN);
|
|
|
|
flags &= ~Account.FLAGS_DELETE_POLICY_MASK;
|
|
|
|
flags |= Account.DELETE_POLICY_ON_DELETE << Account.FLAGS_DELETE_POLICY_SHIFT;
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put(AccountColumns.FLAGS, flags);
|
|
|
|
long accountId = c.getLong(Account.CONTENT_ID_COLUMN);
|
|
|
|
Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
|
|
|
|
resolver.update(uri, cv, null, null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-28 01:29:35 +00:00
|
|
|
private void setComponentEnabled(Class<?> clazz, boolean enabled) {
|
|
|
|
final ComponentName c = new ComponentName(this, clazz.getName());
|
|
|
|
getPackageManager().setComponentEnabledSetting(c,
|
|
|
|
enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
|
|
|
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
|
|
|
PackageManager.DONT_KILL_APP);
|
|
|
|
}
|
2011-01-14 20:00:17 +00:00
|
|
|
|
|
|
|
private void onSystemAccountChanged() {
|
2013-05-26 04:32:32 +00:00
|
|
|
LogUtils.i(Logging.LOG_TAG, "System accounts updated.");
|
2012-09-03 18:46:10 +00:00
|
|
|
reconcileAndStartServices();
|
2011-01-14 20:00:17 +00:00
|
|
|
}
|
2010-05-28 01:29:35 +00:00
|
|
|
}
|