2010-02-02 19:17:48 +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.
|
|
|
|
*/
|
|
|
|
|
2011-06-27 19:12:41 +00:00
|
|
|
package com.android.email.service;
|
2010-02-02 19:17:48 +00:00
|
|
|
|
2012-08-21 22:21:40 +00:00
|
|
|
import android.accounts.AccountManager;
|
2013-07-26 23:49:06 +00:00
|
|
|
import android.accounts.AccountManagerCallback;
|
2012-08-21 22:21:40 +00:00
|
|
|
import android.accounts.AccountManagerFuture;
|
|
|
|
import android.accounts.AuthenticatorException;
|
|
|
|
import android.accounts.OperationCanceledException;
|
2012-04-25 17:26:46 +00:00
|
|
|
import android.app.Service;
|
2014-07-24 22:26:47 +00:00
|
|
|
import android.content.ComponentName;
|
2012-08-23 05:25:42 +00:00
|
|
|
import android.content.ContentProviderClient;
|
2012-08-21 22:21:40 +00:00
|
|
|
import android.content.ContentResolver;
|
|
|
|
import android.content.ContentUris;
|
|
|
|
import android.content.ContentValues;
|
2010-02-02 19:17:48 +00:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
2013-10-11 19:12:53 +00:00
|
|
|
import android.content.pm.ActivityInfo;
|
2014-07-24 22:26:47 +00:00
|
|
|
import android.content.pm.PackageManager;
|
2013-10-11 19:12:53 +00:00
|
|
|
import android.content.res.Configuration;
|
2012-06-28 17:40:46 +00:00
|
|
|
import android.content.res.Resources;
|
|
|
|
import android.content.res.TypedArray;
|
|
|
|
import android.content.res.XmlResourceParser;
|
2012-08-21 22:21:40 +00:00
|
|
|
import android.database.Cursor;
|
|
|
|
import android.net.Uri;
|
2012-04-25 17:26:46 +00:00
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.IBinder;
|
|
|
|
import android.os.RemoteException;
|
2012-08-21 22:21:40 +00:00
|
|
|
import android.provider.CalendarContract;
|
2012-08-23 05:25:42 +00:00
|
|
|
import android.provider.CalendarContract.Calendars;
|
|
|
|
import android.provider.CalendarContract.SyncState;
|
2012-08-21 22:21:40 +00:00
|
|
|
import android.provider.ContactsContract;
|
2013-09-24 22:57:59 +00:00
|
|
|
import android.provider.ContactsContract.RawContacts;
|
2012-08-23 05:25:42 +00:00
|
|
|
import android.provider.SyncStateContract;
|
2014-08-07 22:36:20 +00:00
|
|
|
import android.support.annotation.Nullable;
|
2014-03-14 22:48:10 +00:00
|
|
|
import android.text.TextUtils;
|
2012-03-02 18:31:11 +00:00
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
import com.android.email.R;
|
2014-07-28 18:34:25 +00:00
|
|
|
import com.android.emailcommon.VendorPolicyLoader;
|
2012-06-28 17:40:46 +00:00
|
|
|
import com.android.emailcommon.provider.Account;
|
2012-08-21 22:21:40 +00:00
|
|
|
import com.android.emailcommon.provider.EmailContent;
|
|
|
|
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
2014-04-11 21:42:28 +00:00
|
|
|
import com.android.emailcommon.provider.EmailContent.HostAuthColumns;
|
2012-08-23 05:25:42 +00:00
|
|
|
import com.android.emailcommon.provider.HostAuth;
|
2011-06-27 19:12:41 +00:00
|
|
|
import com.android.emailcommon.service.EmailServiceProxy;
|
2014-06-12 17:59:57 +00:00
|
|
|
import com.android.emailcommon.service.EmailServiceStatus;
|
2014-07-10 22:08:29 +00:00
|
|
|
import com.android.emailcommon.service.EmailServiceVersion;
|
2014-07-02 20:29:58 +00:00
|
|
|
import com.android.emailcommon.service.HostAuthCompat;
|
2011-06-27 19:12:41 +00:00
|
|
|
import com.android.emailcommon.service.IEmailService;
|
|
|
|
import com.android.emailcommon.service.IEmailServiceCallback;
|
2012-04-25 17:26:46 +00:00
|
|
|
import com.android.emailcommon.service.SearchParams;
|
2013-09-12 23:04:37 +00:00
|
|
|
import com.android.emailcommon.service.ServiceProxy;
|
2012-06-28 17:40:46 +00:00
|
|
|
import com.android.emailcommon.service.SyncWindow;
|
2013-05-26 04:32:32 +00:00
|
|
|
import com.android.mail.utils.LogUtils;
|
2013-08-09 18:50:48 +00:00
|
|
|
import com.google.common.collect.ImmutableMap;
|
2013-07-22 22:26:34 +00:00
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
2013-08-09 18:50:48 +00:00
|
|
|
import java.util.Collection;
|
2013-03-05 17:45:10 +00:00
|
|
|
import java.util.Map;
|
2011-06-27 19:12:41 +00:00
|
|
|
|
2010-02-02 19:17:48 +00:00
|
|
|
/**
|
2011-06-27 19:12:41 +00:00
|
|
|
* Utility functions for EmailService support.
|
2010-02-02 19:17:48 +00:00
|
|
|
*/
|
2011-06-27 19:12:41 +00:00
|
|
|
public class EmailServiceUtils {
|
2013-09-12 23:04:37 +00:00
|
|
|
/**
|
|
|
|
* Ask a service to kill its process. This is used when an account is deleted so that
|
|
|
|
* no background thread that happens to be running will continue, possibly hitting an
|
|
|
|
* NPE or other error when trying to operate on an account that no longer exists.
|
|
|
|
* TODO: This is kind of a hack, it's only needed because we fail so badly if an account
|
|
|
|
* is deleted out from under us while a sync or other operation is in progress. It would
|
|
|
|
* be a lot cleaner if our background services could handle this without crashing.
|
|
|
|
*/
|
|
|
|
public static void killService(Context context, String protocol) {
|
|
|
|
EmailServiceInfo info = getServiceInfo(context, protocol);
|
|
|
|
if (info != null && info.intentAction != null) {
|
|
|
|
final Intent serviceIntent = getServiceIntent(info);
|
|
|
|
serviceIntent.putExtra(ServiceProxy.EXTRA_FORCE_SHUTDOWN, true);
|
|
|
|
context.startService(serviceIntent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-02 19:17:48 +00:00
|
|
|
/**
|
2012-06-28 17:40:46 +00:00
|
|
|
* Starts an EmailService by protocol
|
2010-02-02 19:17:48 +00:00
|
|
|
*/
|
2012-06-28 17:40:46 +00:00
|
|
|
public static void startService(Context context, String protocol) {
|
|
|
|
EmailServiceInfo info = getServiceInfo(context, protocol);
|
|
|
|
if (info != null && info.intentAction != null) {
|
2013-08-28 21:31:09 +00:00
|
|
|
final Intent serviceIntent = getServiceIntent(info);
|
|
|
|
context.startService(serviceIntent);
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
2010-02-02 19:17:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-06-28 17:40:46 +00:00
|
|
|
* Starts all remote services
|
2010-02-02 19:17:48 +00:00
|
|
|
*/
|
2012-06-28 17:40:46 +00:00
|
|
|
public static void startRemoteServices(Context context) {
|
|
|
|
for (EmailServiceInfo info: getServiceInfoList(context)) {
|
|
|
|
if (info.intentAction != null) {
|
2013-08-28 21:31:09 +00:00
|
|
|
final Intent serviceIntent = getServiceIntent(info);
|
|
|
|
context.startService(serviceIntent);
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether or not remote services are present on device
|
|
|
|
*/
|
|
|
|
public static boolean areRemoteServicesInstalled(Context context) {
|
|
|
|
for (EmailServiceInfo info: getServiceInfoList(context)) {
|
|
|
|
if (info.intentAction != null) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts all remote services
|
|
|
|
*/
|
|
|
|
public static void setRemoteServicesLogging(Context context, int debugBits) {
|
|
|
|
for (EmailServiceInfo info: getServiceInfoList(context)) {
|
|
|
|
if (info.intentAction != null) {
|
|
|
|
EmailServiceProxy service =
|
2013-07-30 02:11:41 +00:00
|
|
|
EmailServiceUtils.getService(context, info.protocol);
|
2012-06-28 17:40:46 +00:00
|
|
|
if (service != null) {
|
|
|
|
try {
|
|
|
|
service.setLogging(debugBits);
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
// Move along, nothing to see
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-02-13 02:56:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-06-27 19:12:41 +00:00
|
|
|
* Determine if the EmailService is available
|
2011-02-13 02:56:09 +00:00
|
|
|
*/
|
2012-06-28 17:40:46 +00:00
|
|
|
public static boolean isServiceAvailable(Context context, String protocol) {
|
|
|
|
EmailServiceInfo info = getServiceInfo(context, protocol);
|
|
|
|
if (info == null) return false;
|
|
|
|
if (info.klass != null) return true;
|
2013-08-28 21:31:09 +00:00
|
|
|
final Intent serviceIntent = getServiceIntent(info);
|
|
|
|
return new EmailServiceProxy(context, serviceIntent).test();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static Intent getServiceIntent(EmailServiceInfo info) {
|
|
|
|
final Intent serviceIntent = new Intent(info.intentAction);
|
|
|
|
serviceIntent.setPackage(info.intentPackage);
|
|
|
|
return serviceIntent;
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* For a given account id, return a service proxy if applicable, or null.
|
|
|
|
*
|
|
|
|
* @param accountId the message of interest
|
2013-10-11 19:12:53 +00:00
|
|
|
* @return service proxy, or null if n/a
|
2012-06-28 17:40:46 +00:00
|
|
|
*/
|
2013-07-30 02:11:41 +00:00
|
|
|
public static EmailServiceProxy getServiceForAccount(Context context, long accountId) {
|
|
|
|
return getService(context, Account.getProtocol(context, accountId));
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Holder of service information (currently just name and class/intent); if there is a class
|
|
|
|
* member, this is a (local, i.e. same process) service; otherwise, this is a remote service
|
|
|
|
*/
|
|
|
|
public static class EmailServiceInfo {
|
|
|
|
public String protocol;
|
|
|
|
public String name;
|
|
|
|
public String accountType;
|
|
|
|
Class<? extends Service> klass;
|
|
|
|
String intentAction;
|
2013-08-28 21:31:09 +00:00
|
|
|
String intentPackage;
|
2012-06-28 17:40:46 +00:00
|
|
|
public int port;
|
|
|
|
public int portSsl;
|
|
|
|
public boolean defaultSsl;
|
|
|
|
public boolean offerTls;
|
|
|
|
public boolean offerCerts;
|
2014-01-22 00:57:06 +00:00
|
|
|
public boolean offerOAuth;
|
2012-06-28 17:40:46 +00:00
|
|
|
public boolean usesSmtp;
|
|
|
|
public boolean offerLocalDeletes;
|
|
|
|
public int defaultLocalDeletes;
|
|
|
|
public boolean offerPrefix;
|
|
|
|
public boolean usesAutodiscover;
|
|
|
|
public boolean offerLookback;
|
|
|
|
public int defaultLookback;
|
|
|
|
public boolean syncChanges;
|
|
|
|
public boolean syncContacts;
|
|
|
|
public boolean syncCalendar;
|
|
|
|
public boolean offerAttachmentPreload;
|
|
|
|
public CharSequence[] syncIntervalStrings;
|
|
|
|
public CharSequence[] syncIntervals;
|
|
|
|
public int defaultSyncInterval;
|
2012-08-16 21:11:11 +00:00
|
|
|
public String inferPrefix;
|
2012-08-24 02:40:47 +00:00
|
|
|
public boolean offerLoadMore;
|
2013-10-29 17:35:03 +00:00
|
|
|
public boolean offerMoveTo;
|
2012-09-08 20:08:50 +00:00
|
|
|
public boolean requiresSetup;
|
2012-09-20 20:34:13 +00:00
|
|
|
public boolean hide;
|
2014-07-31 17:40:53 +00:00
|
|
|
public boolean isGmailStub;
|
2012-06-28 17:40:46 +00:00
|
|
|
|
2012-09-20 20:34:13 +00:00
|
|
|
@Override
|
2012-06-28 17:40:46 +00:00
|
|
|
public String toString() {
|
|
|
|
StringBuilder sb = new StringBuilder("Protocol: ");
|
|
|
|
sb.append(protocol);
|
|
|
|
sb.append(", ");
|
|
|
|
sb.append(klass != null ? "Local" : "Remote");
|
2012-09-08 01:31:04 +00:00
|
|
|
sb.append(" , Account Type: ");
|
|
|
|
sb.append(accountType);
|
2012-06-28 17:40:46 +00:00
|
|
|
return sb.toString();
|
|
|
|
}
|
2010-02-02 23:06:52 +00:00
|
|
|
}
|
|
|
|
|
2013-07-30 02:11:41 +00:00
|
|
|
public static EmailServiceProxy getService(Context context, String protocol) {
|
2012-08-16 17:13:00 +00:00
|
|
|
EmailServiceInfo info = null;
|
2012-06-28 17:40:46 +00:00
|
|
|
// Handle the degenerate case here (account might have been deleted)
|
2012-08-16 17:13:00 +00:00
|
|
|
if (protocol != null) {
|
|
|
|
info = getServiceInfo(context, protocol);
|
|
|
|
}
|
|
|
|
if (info == null) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Returning NullService for %s", protocol);
|
2013-07-30 02:11:41 +00:00
|
|
|
return new EmailServiceProxy(context, NullService.class);
|
2012-08-23 05:25:42 +00:00
|
|
|
} else {
|
2013-07-30 02:11:41 +00:00
|
|
|
return getServiceFromInfo(context, info);
|
2012-08-23 05:25:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:11:41 +00:00
|
|
|
public static EmailServiceProxy getServiceFromInfo(Context context, EmailServiceInfo info) {
|
2012-08-23 05:25:42 +00:00
|
|
|
if (info.klass != null) {
|
2013-07-30 02:11:41 +00:00
|
|
|
return new EmailServiceProxy(context, info.klass);
|
2012-06-28 17:40:46 +00:00
|
|
|
} else {
|
2013-08-28 21:31:09 +00:00
|
|
|
final Intent serviceIntent = getServiceIntent(info);
|
|
|
|
return new EmailServiceProxy(context, serviceIntent);
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
2011-06-27 19:12:41 +00:00
|
|
|
}
|
|
|
|
|
2012-09-08 20:08:50 +00:00
|
|
|
public static EmailServiceInfo getServiceInfoForAccount(Context context, long accountId) {
|
|
|
|
String protocol = Account.getProtocol(context, accountId);
|
|
|
|
return getServiceInfo(context, protocol);
|
|
|
|
}
|
|
|
|
|
2013-10-11 19:12:53 +00:00
|
|
|
public static EmailServiceInfo getServiceInfo(Context context, String protocol) {
|
|
|
|
return getServiceMap(context).get(protocol);
|
2011-06-27 19:12:41 +00:00
|
|
|
}
|
|
|
|
|
2013-10-11 19:12:53 +00:00
|
|
|
public static Collection<EmailServiceInfo> getServiceInfoList(Context context) {
|
|
|
|
return getServiceMap(context).values();
|
2010-02-24 19:51:59 +00:00
|
|
|
}
|
|
|
|
|
2012-08-21 22:21:40 +00:00
|
|
|
private static void finishAccountManagerBlocker(AccountManagerFuture<?> future) {
|
|
|
|
try {
|
|
|
|
// Note: All of the potential errors are simply logged
|
|
|
|
// here, as there is nothing to actually do about them.
|
|
|
|
future.getResult();
|
|
|
|
} catch (OperationCanceledException e) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, e, "finishAccountManagerBlocker");
|
2012-08-21 22:21:40 +00:00
|
|
|
} catch (AuthenticatorException e) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, e, "finishAccountManagerBlocker");
|
2012-08-21 22:21:40 +00:00
|
|
|
} catch (IOException e) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, e, "finishAccountManagerBlocker");
|
2012-08-21 22:21:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-26 23:49:06 +00:00
|
|
|
/**
|
|
|
|
* Add an account to the AccountManager.
|
|
|
|
* @param context Our {@link Context}.
|
|
|
|
* @param account The {@link Account} we're adding.
|
|
|
|
* @param email Whether the user wants to sync email on this account.
|
|
|
|
* @param calendar Whether the user wants to sync calendar on this account.
|
|
|
|
* @param contacts Whether the user wants to sync contacts on this account.
|
|
|
|
* @param callback A callback for when the AccountManager is done.
|
|
|
|
* @return The result of {@link AccountManager#addAccount}.
|
|
|
|
*/
|
|
|
|
public static AccountManagerFuture<Bundle> setupAccountManagerAccount(final Context context,
|
|
|
|
final Account account, final boolean email, final boolean calendar,
|
|
|
|
final boolean contacts, final AccountManagerCallback<Bundle> callback) {
|
|
|
|
final HostAuth hostAuthRecv =
|
|
|
|
HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv);
|
2014-07-24 20:28:26 +00:00
|
|
|
return setupAccountManagerAccount(context, account, email, calendar, contacts,
|
|
|
|
hostAuthRecv, callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an account to the AccountManager.
|
|
|
|
* @param context Our {@link Context}.
|
|
|
|
* @param account The {@link Account} we're adding.
|
|
|
|
* @param email Whether the user wants to sync email on this account.
|
|
|
|
* @param calendar Whether the user wants to sync calendar on this account.
|
|
|
|
* @param contacts Whether the user wants to sync contacts on this account.
|
|
|
|
* @param hostAuth HostAuth that identifies the protocol and password for this account.
|
|
|
|
* @param callback A callback for when the AccountManager is done.
|
|
|
|
* @return The result of {@link AccountManager#addAccount}.
|
|
|
|
*/
|
|
|
|
public static AccountManagerFuture<Bundle> setupAccountManagerAccount(final Context context,
|
|
|
|
final Account account, final boolean email, final boolean calendar,
|
|
|
|
final boolean contacts, final HostAuth hostAuth,
|
|
|
|
final AccountManagerCallback<Bundle> callback) {
|
|
|
|
if (hostAuth == null) {
|
2013-07-26 23:49:06 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
// Set up username/password
|
2014-07-24 20:28:26 +00:00
|
|
|
final Bundle options = new Bundle(5);
|
2013-07-26 23:49:06 +00:00
|
|
|
options.putString(EasAuthenticatorService.OPTIONS_USERNAME, account.mEmailAddress);
|
2014-07-24 20:28:26 +00:00
|
|
|
options.putString(EasAuthenticatorService.OPTIONS_PASSWORD, hostAuth.mPassword);
|
2013-07-26 23:49:06 +00:00
|
|
|
options.putBoolean(EasAuthenticatorService.OPTIONS_CONTACTS_SYNC_ENABLED, contacts);
|
|
|
|
options.putBoolean(EasAuthenticatorService.OPTIONS_CALENDAR_SYNC_ENABLED, calendar);
|
|
|
|
options.putBoolean(EasAuthenticatorService.OPTIONS_EMAIL_SYNC_ENABLED, email);
|
2014-07-24 20:28:26 +00:00
|
|
|
final EmailServiceInfo info = getServiceInfo(context, hostAuth.mProtocol);
|
2013-07-26 23:49:06 +00:00
|
|
|
return AccountManager.get(context).addAccount(info.accountType, null, null, options, null,
|
|
|
|
callback, null);
|
|
|
|
}
|
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
public static void updateAccountManagerType(Context context,
|
2013-07-25 00:00:35 +00:00
|
|
|
android.accounts.Account amAccount, final Map<String, String> protocolMap) {
|
2013-03-05 17:45:10 +00:00
|
|
|
final ContentResolver resolver = context.getContentResolver();
|
|
|
|
final Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION,
|
2012-08-21 22:21:40 +00:00
|
|
|
AccountColumns.EMAIL_ADDRESS + "=?", new String[] { amAccount.name }, null);
|
|
|
|
// That's odd, isn't it?
|
|
|
|
if (c == null) return;
|
|
|
|
try {
|
|
|
|
if (c.moveToNext()) {
|
|
|
|
// Get the EmailProvider Account/HostAuth
|
2013-03-05 17:45:10 +00:00
|
|
|
final Account account = new Account();
|
2012-08-21 22:21:40 +00:00
|
|
|
account.restore(c);
|
2013-03-05 17:45:10 +00:00
|
|
|
final HostAuth hostAuth =
|
2012-08-21 22:21:40 +00:00
|
|
|
HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv);
|
2013-03-05 17:45:10 +00:00
|
|
|
if (hostAuth == null) {
|
|
|
|
return;
|
|
|
|
}
|
2012-08-21 22:21:40 +00:00
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
final String newProtocol = protocolMap.get(hostAuth.mProtocol);
|
|
|
|
if (newProtocol == null) {
|
|
|
|
// This account doesn't need updating.
|
2012-08-23 05:25:42 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-07-22 22:26:34 +00:00
|
|
|
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Converting %s to %s", amAccount.name, newProtocol);
|
2012-08-23 05:25:42 +00:00
|
|
|
|
2013-03-05 17:45:10 +00:00
|
|
|
final ContentValues accountValues = new ContentValues();
|
2012-08-21 22:21:40 +00:00
|
|
|
int oldFlags = account.mFlags;
|
|
|
|
|
|
|
|
// Mark the provider account incomplete so it can't get reconciled away
|
|
|
|
account.mFlags |= Account.FLAGS_INCOMPLETE;
|
|
|
|
accountValues.put(AccountColumns.FLAGS, account.mFlags);
|
2013-03-05 17:45:10 +00:00
|
|
|
final Uri accountUri = ContentUris.withAppendedId(Account.CONTENT_URI, account.mId);
|
2012-08-21 22:21:40 +00:00
|
|
|
resolver.update(accountUri, accountValues, null, null);
|
|
|
|
|
|
|
|
// Change the HostAuth to reference the new protocol; this has to be done before
|
|
|
|
// trying to create the AccountManager account (below)
|
2013-03-05 17:45:10 +00:00
|
|
|
final ContentValues hostValues = new ContentValues();
|
2014-04-11 21:42:28 +00:00
|
|
|
hostValues.put(HostAuthColumns.PROTOCOL, newProtocol);
|
2012-08-21 22:21:40 +00:00
|
|
|
resolver.update(ContentUris.withAppendedId(HostAuth.CONTENT_URI, hostAuth.mId),
|
|
|
|
hostValues, null, null);
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Updated HostAuths");
|
2012-08-21 22:21:40 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
// Get current settings for the existing AccountManager account
|
|
|
|
boolean email = ContentResolver.getSyncAutomatically(amAccount,
|
|
|
|
EmailContent.AUTHORITY);
|
2012-08-23 05:25:42 +00:00
|
|
|
if (!email) {
|
|
|
|
// Try our old provider name
|
|
|
|
email = ContentResolver.getSyncAutomatically(amAccount,
|
|
|
|
"com.android.email.provider");
|
|
|
|
}
|
2013-03-05 17:45:10 +00:00
|
|
|
final boolean contacts = ContentResolver.getSyncAutomatically(amAccount,
|
2012-08-21 22:21:40 +00:00
|
|
|
ContactsContract.AUTHORITY);
|
2013-03-05 17:45:10 +00:00
|
|
|
final boolean calendar = ContentResolver.getSyncAutomatically(amAccount,
|
2012-08-21 22:21:40 +00:00
|
|
|
CalendarContract.AUTHORITY);
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Email: %s, Contacts: %s Calendar: %s",
|
|
|
|
email, contacts, calendar);
|
2012-08-23 05:25:42 +00:00
|
|
|
|
|
|
|
// Get sync keys for calendar/contacts
|
2013-03-05 17:45:10 +00:00
|
|
|
final String amName = amAccount.name;
|
|
|
|
final String oldType = amAccount.type;
|
2012-08-23 05:25:42 +00:00
|
|
|
ContentProviderClient client = context.getContentResolver()
|
|
|
|
.acquireContentProviderClient(CalendarContract.CONTENT_URI);
|
|
|
|
byte[] calendarSyncKey = null;
|
|
|
|
try {
|
|
|
|
calendarSyncKey = SyncStateContract.Helpers.get(client,
|
|
|
|
asCalendarSyncAdapter(SyncState.CONTENT_URI, amName, oldType),
|
|
|
|
new android.accounts.Account(amName, oldType));
|
|
|
|
} catch (RemoteException e) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Get calendar key FAILED");
|
2012-08-23 05:25:42 +00:00
|
|
|
} finally {
|
|
|
|
client.release();
|
|
|
|
}
|
|
|
|
client = context.getContentResolver()
|
|
|
|
.acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
|
|
|
|
byte[] contactsSyncKey = null;
|
|
|
|
try {
|
|
|
|
contactsSyncKey = SyncStateContract.Helpers.get(client,
|
|
|
|
ContactsContract.SyncState.CONTENT_URI,
|
|
|
|
new android.accounts.Account(amName, oldType));
|
|
|
|
} catch (RemoteException e) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Get contacts key FAILED");
|
2012-08-23 05:25:42 +00:00
|
|
|
} finally {
|
|
|
|
client.release();
|
|
|
|
}
|
|
|
|
if (calendarSyncKey != null) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Got calendar key: %s",
|
|
|
|
new String(calendarSyncKey));
|
2012-08-23 05:25:42 +00:00
|
|
|
}
|
|
|
|
if (contactsSyncKey != null) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Got contacts key: %s",
|
|
|
|
new String(contactsSyncKey));
|
2012-08-23 05:25:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set up a new AccountManager account with new type and old settings
|
2013-07-26 23:49:06 +00:00
|
|
|
AccountManagerFuture<?> amFuture = setupAccountManagerAccount(context, account,
|
|
|
|
email, calendar, contacts, null);
|
2012-08-23 05:25:42 +00:00
|
|
|
finishAccountManagerBlocker(amFuture);
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Created new AccountManager account");
|
2012-08-21 22:21:40 +00:00
|
|
|
|
2013-09-24 22:57:59 +00:00
|
|
|
// TODO: Clean up how we determine the type.
|
|
|
|
final String accountType = protocolMap.get(hostAuth.mProtocol + "_type");
|
|
|
|
// Move calendar and contacts data from the old account to the new one.
|
|
|
|
// We must do this before deleting the old account or the data is lost.
|
|
|
|
moveCalendarData(context.getContentResolver(), amName, oldType, accountType);
|
|
|
|
moveContactsData(context.getContentResolver(), amName, oldType, accountType);
|
Clear exchange sync keys upon app upgrade
b/10211620
The problem here is that on app upgrade, we need to change
the types of all email accounts. To do this, we have to
create new accounts and delete the old ones. This resulted
in calendar and contacts data getting deleted.
But we were copying over the last sync keys from the old
account, so on the next sync, we would only get new data.
This means that all of the data that we had gotten on
a previous sync would never be sent again, so calendar
events and contacts would be missing forever.
Now, we just don't migrate the old sync keys. This means
that on the next sync, we'll get all data, and restore
our original state.
This is still not ideal, because it means that any locally
created data that has not yet been synced will be lost
(b/10805685), but it's much better than it was.
Change-Id: I150c4dbdf490a8f3880261e2469795896ebfeab5
2013-09-17 23:43:07 +00:00
|
|
|
|
2012-08-21 22:21:40 +00:00
|
|
|
// Delete the AccountManager account
|
2012-08-23 05:25:42 +00:00
|
|
|
amFuture = AccountManager.get(context)
|
2012-08-21 22:21:40 +00:00
|
|
|
.removeAccount(amAccount, null, null);
|
|
|
|
finishAccountManagerBlocker(amFuture);
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Deleted old AccountManager account");
|
2012-08-21 22:21:40 +00:00
|
|
|
|
2012-08-23 05:25:42 +00:00
|
|
|
// Restore sync keys for contacts/calendar
|
2013-09-24 22:57:59 +00:00
|
|
|
|
2013-07-22 22:26:34 +00:00
|
|
|
if (accountType != null &&
|
|
|
|
calendarSyncKey != null && calendarSyncKey.length != 0) {
|
2012-08-23 05:25:42 +00:00
|
|
|
client = context.getContentResolver()
|
|
|
|
.acquireContentProviderClient(CalendarContract.CONTENT_URI);
|
|
|
|
try {
|
|
|
|
SyncStateContract.Helpers.set(client,
|
|
|
|
asCalendarSyncAdapter(SyncState.CONTENT_URI, amName,
|
2013-07-22 22:26:34 +00:00
|
|
|
accountType),
|
|
|
|
new android.accounts.Account(amName, accountType),
|
2012-08-23 05:25:42 +00:00
|
|
|
calendarSyncKey);
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Set calendar key...");
|
2012-08-23 05:25:42 +00:00
|
|
|
} catch (RemoteException e) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Set calendar key FAILED");
|
2012-08-23 05:25:42 +00:00
|
|
|
} finally {
|
|
|
|
client.release();
|
|
|
|
}
|
|
|
|
}
|
2013-07-22 22:26:34 +00:00
|
|
|
if (accountType != null &&
|
|
|
|
contactsSyncKey != null && contactsSyncKey.length != 0) {
|
2012-08-23 05:25:42 +00:00
|
|
|
client = context.getContentResolver()
|
|
|
|
.acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
|
|
|
|
try {
|
|
|
|
SyncStateContract.Helpers.set(client,
|
|
|
|
ContactsContract.SyncState.CONTENT_URI,
|
2013-07-22 22:26:34 +00:00
|
|
|
new android.accounts.Account(amName, accountType),
|
2012-08-23 05:25:42 +00:00
|
|
|
contactsSyncKey);
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Set contacts key...");
|
2012-08-23 05:25:42 +00:00
|
|
|
} catch (RemoteException e) {
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Set contacts key FAILED");
|
2012-08-23 05:25:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// That's all folks!
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "Account update completed.");
|
2012-08-21 22:21:40 +00:00
|
|
|
} finally {
|
|
|
|
// Clear the incomplete flag on the provider account
|
|
|
|
accountValues.put(AccountColumns.FLAGS, oldFlags);
|
|
|
|
resolver.update(accountUri, accountValues, null, null);
|
2014-05-06 18:22:10 +00:00
|
|
|
LogUtils.w(LogUtils.TAG, "[Incomplete flag cleared]");
|
2012-08-21 22:21:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-24 22:57:59 +00:00
|
|
|
private static void moveCalendarData(final ContentResolver resolver, final String name,
|
|
|
|
final String oldType, final String newType) {
|
|
|
|
final Uri oldCalendars = Calendars.CONTENT_URI.buildUpon()
|
|
|
|
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
|
|
|
|
.appendQueryParameter(Calendars.ACCOUNT_NAME, name)
|
|
|
|
.appendQueryParameter(Calendars.ACCOUNT_TYPE, oldType)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
// Update this calendar to have the new account type.
|
|
|
|
final ContentValues values = new ContentValues();
|
|
|
|
values.put(CalendarContract.Calendars.ACCOUNT_TYPE, newType);
|
|
|
|
resolver.update(oldCalendars, values,
|
|
|
|
Calendars.ACCOUNT_NAME + "=? AND " + Calendars.ACCOUNT_TYPE + "=?",
|
|
|
|
new String[] {name, oldType});
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void moveContactsData(final ContentResolver resolver, final String name,
|
|
|
|
final String oldType, final String newType) {
|
|
|
|
final Uri oldContacts = RawContacts.CONTENT_URI.buildUpon()
|
|
|
|
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
|
|
|
.appendQueryParameter(RawContacts.ACCOUNT_NAME, name)
|
|
|
|
.appendQueryParameter(RawContacts.ACCOUNT_TYPE, oldType)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
// Update this calendar to have the new account type.
|
|
|
|
final ContentValues values = new ContentValues();
|
|
|
|
values.put(CalendarContract.Calendars.ACCOUNT_TYPE, newType);
|
|
|
|
resolver.update(oldContacts, values, null, null);
|
|
|
|
}
|
|
|
|
|
2013-10-11 19:12:53 +00:00
|
|
|
private static final Configuration sOldConfiguration = new Configuration();
|
|
|
|
private static Map<String, EmailServiceInfo> sServiceMap = null;
|
|
|
|
private static final Object sServiceMapLock = new Object();
|
|
|
|
|
2010-02-02 23:06:52 +00:00
|
|
|
/**
|
2012-06-28 17:40:46 +00:00
|
|
|
* Parse services.xml file to find our available email services
|
2010-02-02 23:06:52 +00:00
|
|
|
*/
|
2013-10-11 19:12:53 +00:00
|
|
|
private static Map<String, EmailServiceInfo> getServiceMap(final Context context) {
|
|
|
|
synchronized (sServiceMapLock) {
|
|
|
|
/**
|
|
|
|
* We cache localized strings here, so make sure to regenerate the service map if
|
|
|
|
* the locale changes
|
|
|
|
*/
|
|
|
|
if (sServiceMap == null) {
|
|
|
|
sOldConfiguration.setTo(context.getResources().getConfiguration());
|
|
|
|
}
|
2013-08-09 18:50:48 +00:00
|
|
|
|
2013-10-11 19:12:53 +00:00
|
|
|
final int delta =
|
|
|
|
sOldConfiguration.updateFrom(context.getResources().getConfiguration());
|
2013-08-09 18:50:48 +00:00
|
|
|
|
2013-10-11 19:12:53 +00:00
|
|
|
if (sServiceMap != null
|
|
|
|
&& !Configuration.needNewResources(delta, ActivityInfo.CONFIG_LOCALE)) {
|
|
|
|
return sServiceMap;
|
|
|
|
}
|
|
|
|
|
|
|
|
final ImmutableMap.Builder<String, EmailServiceInfo> builder = ImmutableMap.builder();
|
2014-08-25 21:12:16 +00:00
|
|
|
if (!context.getResources().getBoolean(R.bool.enable_services)) {
|
|
|
|
// Return an empty map if services have been disabled because this is the Email
|
|
|
|
// Tombstone app.
|
|
|
|
sServiceMap = builder.build();
|
|
|
|
return sServiceMap;
|
|
|
|
}
|
2013-10-11 19:12:53 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
final Resources res = context.getResources();
|
|
|
|
final XmlResourceParser xml = res.getXml(R.xml.services);
|
|
|
|
int xmlEventType;
|
|
|
|
// walk through senders.xml file.
|
|
|
|
while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) {
|
|
|
|
if (xmlEventType == XmlResourceParser.START_TAG &&
|
|
|
|
"emailservice".equals(xml.getName())) {
|
|
|
|
final EmailServiceInfo info = new EmailServiceInfo();
|
|
|
|
final TypedArray ta =
|
|
|
|
res.obtainAttributes(xml, R.styleable.EmailServiceInfo);
|
|
|
|
info.protocol = ta.getString(R.styleable.EmailServiceInfo_protocol);
|
|
|
|
info.accountType = ta.getString(R.styleable.EmailServiceInfo_accountType);
|
|
|
|
info.name = ta.getString(R.styleable.EmailServiceInfo_name);
|
|
|
|
info.hide = ta.getBoolean(R.styleable.EmailServiceInfo_hide, false);
|
|
|
|
final String klass =
|
|
|
|
ta.getString(R.styleable.EmailServiceInfo_serviceClass);
|
|
|
|
info.intentAction = ta.getString(R.styleable.EmailServiceInfo_intent);
|
|
|
|
info.intentPackage =
|
|
|
|
ta.getString(R.styleable.EmailServiceInfo_intentPackage);
|
|
|
|
info.defaultSsl =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_defaultSsl, false);
|
|
|
|
info.port = ta.getInteger(R.styleable.EmailServiceInfo_port, 0);
|
|
|
|
info.portSsl = ta.getInteger(R.styleable.EmailServiceInfo_portSsl, 0);
|
|
|
|
info.offerTls = ta.getBoolean(R.styleable.EmailServiceInfo_offerTls, false);
|
|
|
|
info.offerCerts =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_offerCerts, false);
|
2014-01-22 00:57:06 +00:00
|
|
|
info.offerOAuth =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_offerOAuth, false);
|
2013-10-11 19:12:53 +00:00
|
|
|
info.offerLocalDeletes =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_offerLocalDeletes, false);
|
|
|
|
info.defaultLocalDeletes =
|
|
|
|
ta.getInteger(R.styleable.EmailServiceInfo_defaultLocalDeletes,
|
|
|
|
Account.DELETE_POLICY_ON_DELETE);
|
|
|
|
info.offerPrefix =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_offerPrefix, false);
|
|
|
|
info.usesSmtp = ta.getBoolean(R.styleable.EmailServiceInfo_usesSmtp, false);
|
|
|
|
info.usesAutodiscover =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_usesAutodiscover, false);
|
|
|
|
info.offerLookback =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_offerLookback, false);
|
|
|
|
info.defaultLookback =
|
|
|
|
ta.getInteger(R.styleable.EmailServiceInfo_defaultLookback,
|
|
|
|
SyncWindow.SYNC_WINDOW_3_DAYS);
|
|
|
|
info.syncChanges =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_syncChanges, false);
|
|
|
|
info.syncContacts =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_syncContacts, false);
|
|
|
|
info.syncCalendar =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_syncCalendar, false);
|
|
|
|
info.offerAttachmentPreload =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_offerAttachmentPreload,
|
|
|
|
false);
|
|
|
|
info.syncIntervalStrings =
|
|
|
|
ta.getTextArray(R.styleable.EmailServiceInfo_syncIntervalStrings);
|
|
|
|
info.syncIntervals =
|
|
|
|
ta.getTextArray(R.styleable.EmailServiceInfo_syncIntervals);
|
|
|
|
info.defaultSyncInterval =
|
|
|
|
ta.getInteger(R.styleable.EmailServiceInfo_defaultSyncInterval, 15);
|
|
|
|
info.inferPrefix = ta.getString(R.styleable.EmailServiceInfo_inferPrefix);
|
|
|
|
info.offerLoadMore =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_offerLoadMore, false);
|
2013-10-29 17:35:03 +00:00
|
|
|
info.offerMoveTo =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_offerMoveTo, false);
|
2013-10-11 19:12:53 +00:00
|
|
|
info.requiresSetup =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_requiresSetup, false);
|
2014-07-31 17:40:53 +00:00
|
|
|
info.isGmailStub =
|
|
|
|
ta.getBoolean(R.styleable.EmailServiceInfo_isGmailStub, false);
|
2013-10-11 19:12:53 +00:00
|
|
|
|
|
|
|
// Must have either "class" (local) or "intent" (remote)
|
|
|
|
if (klass != null) {
|
|
|
|
try {
|
|
|
|
// noinspection unchecked
|
|
|
|
info.klass = (Class<? extends Service>) Class.forName(klass);
|
|
|
|
} catch (ClassNotFoundException e) {
|
|
|
|
throw new IllegalStateException(
|
|
|
|
"Class not found in service descriptor: " + klass);
|
|
|
|
}
|
|
|
|
}
|
2014-07-31 17:40:53 +00:00
|
|
|
if (info.klass == null &&
|
|
|
|
info.intentAction == null &&
|
|
|
|
!info.isGmailStub) {
|
2012-06-28 17:40:46 +00:00
|
|
|
throw new IllegalStateException(
|
2013-10-11 19:12:53 +00:00
|
|
|
"No class or intent action specified in service descriptor");
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
2013-10-11 19:12:53 +00:00
|
|
|
if (info.klass != null && info.intentAction != null) {
|
|
|
|
throw new IllegalStateException(
|
|
|
|
"Both class and intent action specified in service descriptor");
|
|
|
|
}
|
|
|
|
builder.put(info.protocol, info);
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
|
|
|
}
|
2013-10-11 19:12:53 +00:00
|
|
|
} catch (XmlPullParserException e) {
|
|
|
|
// ignore
|
|
|
|
} catch (IOException e) {
|
|
|
|
// ignore
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
2013-10-11 19:12:53 +00:00
|
|
|
sServiceMap = builder.build();
|
|
|
|
return sServiceMap;
|
2012-04-25 17:26:46 +00:00
|
|
|
}
|
2012-06-28 17:40:46 +00:00
|
|
|
}
|
2014-03-14 22:48:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolves a service name into a protocol name, or null if ambiguous
|
|
|
|
* @param context for loading service map
|
|
|
|
* @param accountType sync adapter service name
|
|
|
|
* @return protocol name or null
|
|
|
|
*/
|
2014-08-07 22:36:20 +00:00
|
|
|
public static @Nullable String getProtocolFromAccountType(final Context context,
|
2014-03-14 22:48:10 +00:00
|
|
|
final String accountType) {
|
2014-08-07 22:36:20 +00:00
|
|
|
if (TextUtils.isEmpty(accountType)) {
|
|
|
|
return null;
|
|
|
|
}
|
2014-03-14 22:48:10 +00:00
|
|
|
final Map <String, EmailServiceInfo> serviceInfoMap = getServiceMap(context);
|
|
|
|
String protocol = null;
|
|
|
|
for (final EmailServiceInfo info : serviceInfoMap.values()) {
|
|
|
|
if (TextUtils.equals(accountType, info.accountType)) {
|
|
|
|
if (!TextUtils.isEmpty(protocol) && !TextUtils.equals(protocol, info.protocol)) {
|
|
|
|
// More than one protocol matches
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
protocol = info.protocol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return protocol;
|
|
|
|
}
|
2012-04-25 17:26:46 +00:00
|
|
|
|
2012-08-23 05:25:42 +00:00
|
|
|
private static Uri asCalendarSyncAdapter(Uri uri, String account, String accountType) {
|
|
|
|
return uri.buildUpon().appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
|
|
|
|
.appendQueryParameter(Calendars.ACCOUNT_NAME, account)
|
|
|
|
.appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
|
|
|
|
}
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
/**
|
|
|
|
* A no-op service that can be returned for non-existent/null protocols
|
|
|
|
*/
|
|
|
|
class NullService implements IEmailService {
|
|
|
|
@Override
|
|
|
|
public IBinder asBinder() {
|
|
|
|
return null;
|
2012-04-25 17:26:46 +00:00
|
|
|
}
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
@Override
|
2014-07-02 20:29:58 +00:00
|
|
|
public Bundle validate(HostAuthCompat hostauth) throws RemoteException {
|
2012-06-28 17:40:46 +00:00
|
|
|
return null;
|
2012-04-25 17:26:46 +00:00
|
|
|
}
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
@Override
|
2014-02-26 16:57:53 +00:00
|
|
|
public void loadAttachment(final IEmailServiceCallback cb, final long accountId,
|
|
|
|
final long attachmentId, final boolean background) throws RemoteException {
|
2012-04-25 17:26:46 +00:00
|
|
|
}
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
@Override
|
2014-06-12 17:59:57 +00:00
|
|
|
public void updateFolderList(long accountId) throws RemoteException {}
|
2012-04-25 17:26:46 +00:00
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
@Override
|
2014-06-12 17:59:57 +00:00
|
|
|
public void setLogging(int flags) throws RemoteException {
|
2012-04-25 17:26:46 +00:00
|
|
|
}
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
@Override
|
|
|
|
public Bundle autoDiscover(String userName, String password) throws RemoteException {
|
|
|
|
return null;
|
2012-04-25 17:26:46 +00:00
|
|
|
}
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
@Override
|
|
|
|
public void sendMeetingResponse(long messageId, int response) throws RemoteException {
|
2012-04-25 17:26:46 +00:00
|
|
|
}
|
|
|
|
|
2014-05-21 20:41:37 +00:00
|
|
|
@Override
|
2014-07-10 22:08:29 +00:00
|
|
|
public void deleteExternalAccountPIMData(final String emailAddress) throws RemoteException {
|
2014-05-21 20:41:37 +00:00
|
|
|
}
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
@Override
|
|
|
|
public int searchMessages(long accountId, SearchParams params, long destMailboxId)
|
|
|
|
throws RemoteException {
|
2012-04-25 17:26:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
@Override
|
|
|
|
public void sendMail(long accountId) throws RemoteException {
|
2012-04-25 17:26:46 +00:00
|
|
|
}
|
2014-02-25 01:34:37 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void pushModify(long accountId) throws RemoteException {
|
|
|
|
}
|
2014-02-26 02:07:07 +00:00
|
|
|
|
|
|
|
@Override
|
2014-06-12 17:59:57 +00:00
|
|
|
public int sync(final long accountId, final Bundle syncExtras) {
|
|
|
|
return EmailServiceStatus.SUCCESS;
|
2014-02-26 02:07:07 +00:00
|
|
|
}
|
|
|
|
|
2014-07-10 22:08:29 +00:00
|
|
|
public int getApiVersion() {
|
|
|
|
return EmailServiceVersion.CURRENT;
|
|
|
|
}
|
2010-02-02 19:17:48 +00:00
|
|
|
}
|
2014-07-24 22:26:47 +00:00
|
|
|
|
2014-07-28 18:34:25 +00:00
|
|
|
public static void setComponentStatus(final Context context, Class<?> clazz, boolean enabled) {
|
2014-07-24 22:26:47 +00:00
|
|
|
final ComponentName c = new ComponentName(context, clazz.getName());
|
|
|
|
context.getPackageManager().setComponentEnabledSetting(c,
|
|
|
|
enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
|
|
|
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
|
|
|
PackageManager.DONT_KILL_APP);
|
|
|
|
}
|
|
|
|
|
2014-07-28 18:34:25 +00:00
|
|
|
/**
|
|
|
|
* This is a helper function that enables the proper Exchange component and disables
|
|
|
|
* the other Exchange component ensuring that only one is enabled at a time.
|
|
|
|
*/
|
|
|
|
public static void enableExchangeComponent(final Context context) {
|
|
|
|
if (VendorPolicyLoader.getInstance(context).useAlternateExchangeStrings()) {
|
|
|
|
LogUtils.d(LogUtils.TAG, "Enabling alternate EAS authenticator");
|
|
|
|
setComponentStatus(context, EasAuthenticatorServiceAlternate.class, true);
|
|
|
|
setComponentStatus(context, EasAuthenticatorService.class, false);
|
|
|
|
} else {
|
|
|
|
LogUtils.d(LogUtils.TAG, "Enabling EAS authenticator");
|
|
|
|
setComponentStatus(context, EasAuthenticatorService.class, true);
|
|
|
|
setComponentStatus(context,
|
|
|
|
EasAuthenticatorServiceAlternate.class, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void disableExchangeComponents(final Context context) {
|
|
|
|
LogUtils.d(LogUtils.TAG, "Disabling EAS authenticators");
|
|
|
|
setComponentStatus(context, EasAuthenticatorServiceAlternate.class, false);
|
|
|
|
setComponentStatus(context, EasAuthenticatorService.class, false);
|
|
|
|
}
|
|
|
|
|
2010-02-02 19:17:48 +00:00
|
|
|
}
|