am bb68c13a: Changes to support smaller email tombstone apk size

* commit 'bb68c13afa630cae058eb40d3ce68644f3f3c8b9':
  Changes to support smaller email tombstone apk size
This commit is contained in:
Paul Westbrook 2014-11-02 15:32:42 +00:00 committed by Android Git Automerger
commit 26f193dab5
95 changed files with 402 additions and 456 deletions

View File

@ -34,6 +34,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, $(unified_email_dir)/src)
LOCAL_SRC_FILES += $(call all-java-files-under, src/com/android)
LOCAL_SRC_FILES += $(call all-java-files-under, provider_src/com/android)
LOCAL_SRC_FILES += $(call all-java-files-under, src/com/beetstra)
LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dir))

View File

@ -3,3 +3,5 @@
-keepclasseswithmembers class * {
public *** newInstance(com.android.emailcommon.provider.Account, android.content.Context);
}
-keepclasses class com.android.email.activity.setup.AccountSetupFinal

View File

@ -37,7 +37,11 @@ public class EmailIntentService extends MailIntentService {
super.onHandleIntent(intent);
if (UIProvider.ACTION_UPDATE_NOTIFICATION.equals(intent.getAction())) {
NotificationController.handleUpdateNotificationIntent(this, intent);
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(this);
if (nc != null) {
nc.handleUpdateNotificationIntent(this, intent);
}
}
LogUtils.v(LOG_TAG, "Handling intent %s", intent);

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2014 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;
import android.content.Context;
import android.content.Intent;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.Attachment;
public interface NotificationController {
void watchForMessages();
void showDownloadForwardFailedNotificationSynchronous(Attachment attachment);
void showLoginFailedNotificationSynchronous(long accountId, boolean incoming);
void cancelLoginFailedNotification(long accountId);
void cancelNotifications(final Context context, final Account account);
void handleUpdateNotificationIntent(Context context, Intent intent);
void showSecurityNeededNotification(Account account);
void showSecurityUnsupportedNotification(Account account);
void showSecurityChangedNotification(Account account);
void cancelSecurityNeededNotification();
void showPasswordExpiringNotificationSynchronous(long accountId);
void showPasswordExpiredNotificationSynchronous(long accountId);
void cancelPasswordExpirationNotifications();
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2014 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;
import android.content.Context;
public interface NotificationControllerCreator {
NotificationController getInstance(Context context);
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2014 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;
import android.content.Context;
public class NotificationControllerCreatorHolder {
private static NotificationControllerCreator sCreator =
new NotificationControllerCreator() {
@Override
public NotificationController getInstance(Context context){
return null;
}
};
public static void setNotificationControllerCreator(
NotificationControllerCreator creator) {
sCreator = creator;
}
public static NotificationControllerCreator getNotificationControllerCreator() {
return sCreator;
}
public static NotificationController getInstance(Context context) {
return getNotificationControllerCreator().getInstance(context);
}
}

View File

@ -32,6 +32,8 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import com.android.email.NotificationController;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.provider.AccountReconciler;
import com.android.email.provider.EmailProvider;
import com.android.email.service.EmailBroadcastProcessorService;
@ -452,7 +454,9 @@ public class SecurityPolicy {
setAccountHoldFlag(context, account, newState);
if (newState) {
// Make sure there's a notification up
NotificationController.getInstance(context).showSecurityNeededNotification(account);
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
nc.showSecurityNeededNotification(account);
}
}
}
@ -499,11 +503,12 @@ public class SecurityPolicy {
setAccountHoldFlag(mContext, account, true);
// Put up an appropriate notification
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(mContext);
if (policy.mProtocolPoliciesUnsupported == null) {
NotificationController.getInstance(mContext).showSecurityNeededNotification(account);
nc.showSecurityNeededNotification(account);
} else {
NotificationController.getInstance(mContext).showSecurityUnsupportedNotification(
account);
nc.showSecurityUnsupportedNotification(account);
}
}
@ -612,14 +617,15 @@ public class SecurityPolicy {
}
boolean setHold = false;
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(mContext);
if (policy.mProtocolPoliciesUnsupported != null) {
// We can't support this, reasons in unsupportedRemotePolicies
LogUtils.d(Logging.LOG_TAG,
"Notify policies for " + account.mDisplayName + " not supported.");
setHold = true;
if (notify) {
NotificationController.getInstance(mContext).showSecurityUnsupportedNotification(
account);
nc.showSecurityUnsupportedNotification(account);
}
// Erase data
Uri uri = EmailProvider.uiUri("uiaccountdata", accountId);
@ -630,8 +636,7 @@ public class SecurityPolicy {
+ " changed.");
if (notify) {
// Notify that policies changed
NotificationController.getInstance(mContext).showSecurityChangedNotification(
account);
nc.showSecurityChangedNotification(account);
}
} else {
LogUtils.d(Logging.LOG_TAG, "Policy is active and unchanged; do not notify.");
@ -642,8 +647,7 @@ public class SecurityPolicy {
" are not being enforced.");
if (notify) {
// Put up a notification
NotificationController.getInstance(mContext).showSecurityNeededNotification(
account);
nc.showSecurityNeededNotification(account);
}
}
// Set/clear the account hold.
@ -655,7 +659,10 @@ public class SecurityPolicy {
* cleared now.
*/
public void clearNotification() {
NotificationController.getInstance(mContext).cancelSecurityNeededNotification();
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(mContext);
nc.cancelSecurityNeededNotification();
}
/**
@ -754,17 +761,17 @@ public class SecurityPolicy {
long expirationDate = getDPM().getPasswordExpiration(mAdminName);
long timeUntilExpiration = expirationDate - System.currentTimeMillis();
boolean expired = timeUntilExpiration < 0;
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
if (!expired) {
// 4. If warning, simply put up a generic notification and report that it came from
// the shortest-expiring account.
NotificationController.getInstance(mContext).showPasswordExpiringNotificationSynchronous(
nextExpiringAccountId);
nc.showPasswordExpiringNotificationSynchronous(nextExpiringAccountId);
} else {
// 5. Actually expired - find all accounts that expire passwords, and wipe them
boolean wiped = wipeExpiredAccounts(context);
if (wiped) {
NotificationController.getInstance(mContext).showPasswordExpiredNotificationSynchronous(
nextExpiringAccountId);
nc.showPasswordExpiredNotificationSynchronous(nextExpiringAccountId);
}
}
}
@ -838,7 +845,10 @@ public class SecurityPolicy {
// Clear security holds (if any)
Account.clearSecurityHoldOnAllAccounts(context);
// Cancel any active notifications (if any are posted)
NotificationController.getInstance(context).cancelPasswordExpirationNotifications();
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
nc.cancelPasswordExpirationNotifications();
break;
case DEVICE_ADMIN_MESSAGE_PASSWORD_EXPIRING:
instance.onPasswordExpiring(instance.mContext);

View File

@ -29,8 +29,9 @@ import android.provider.CalendarContract;
import android.provider.ContactsContract;
import android.text.TextUtils;
import com.android.email.NotificationController;
import com.android.email.R;
import com.android.email.NotificationController;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.SecurityPolicy;
import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
@ -206,7 +207,11 @@ public class AccountReconciler {
exchangeAccountDeleted = true;
}
// Cancel all notifications for this account
NotificationController.cancelNotifications(context, providerAccount);
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
if (nc != null) {
nc.cancelNotifications(context, providerAccount);
}
context.getContentResolver().delete(
EmailProvider.uiUri("uiaccount", providerAccount.mId), null, null);

View File

@ -33,6 +33,7 @@ import android.content.PeriodicSync;
import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@ -66,15 +67,14 @@ import com.android.common.content.ProjectionMap;
import com.android.email.DebugUtils;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.NotificationController;
import com.android.email.SecurityPolicy;
import com.android.email.activity.setup.AccountSecurity;
import com.android.email.activity.setup.AccountSettingsFragment;
import com.android.email.activity.setup.AccountSettingsUtils;
import com.android.email.activity.setup.HeadlessAccountSettingsLoader;
import com.android.email.service.AttachmentService;
import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.Logging;
import com.android.emailcommon.mail.Address;
import com.android.emailcommon.provider.Account;
@ -106,6 +106,7 @@ import com.android.emailcommon.service.IEmailService;
import com.android.emailcommon.service.SearchParams;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.emailcommon.utility.EmailAsyncTask;
import com.android.emailcommon.utility.IntentUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.ex.photo.provider.PhotoContract;
import com.android.mail.preferences.MailPrefs;
@ -168,6 +169,9 @@ public class EmailProvider extends ContentProvider
private static final String BACKUP_DATABASE_NAME = "EmailProviderBackup.db";
private static final String ACCOUNT_MANAGER_JSON_TAG = "accountJson";
private static final String PREFERENCE_FRAGMENT_CLASS_NAME =
"com.android.email.activity.setup.AccountSettingsFragment";
/**
* Notifies that changes happened. Certain UI components, e.g., widgets, can register for this
* {@link android.content.Intent} and update accordingly. However, this can be very broad and
@ -1015,7 +1019,7 @@ public class EmailProvider extends ContentProvider
init(context);
DebugUtils.init(context);
// Do this last, so that EmailContent/EmailProvider are initialized
MailActivityEmail.setServicesEnabledAsync(context);
setServicesEnabledAsync(context);
reconcileAccountsAsync(context);
// Update widgets
@ -3439,8 +3443,7 @@ public class EmailProvider extends ContentProvider
}
if (projectionColumns.contains(UIProvider.AccountColumns.REAUTHENTICATION_INTENT_URI)) {
values.put(UIProvider.AccountColumns.REAUTHENTICATION_INTENT_URI,
HeadlessAccountSettingsLoader.getIncomingSettingsUri(accountId)
.toString());
getIncomingSettingsUri(accountId).toString());
}
if (projectionColumns.contains(UIProvider.AccountColumns.MIME_TYPE)) {
values.put(UIProvider.AccountColumns.MIME_TYPE, EMAIL_APP_MIME_TYPE);
@ -3566,7 +3569,7 @@ public class EmailProvider extends ContentProvider
}
if (projectionColumns.contains(UIProvider.AccountColumns.SETTINGS_FRAGMENT_CLASS)) {
values.put(UIProvider.AccountColumns.SETTINGS_FRAGMENT_CLASS,
AccountSettingsFragment.class.getName());
PREFERENCE_FRAGMENT_CLASS_NAME);
}
if (projectionColumns.contains(UIProvider.AccountColumns.SettingsColumns.REPLY_BEHAVIOR)) {
values.put(UIProvider.AccountColumns.SettingsColumns.REPLY_BEHAVIOR,
@ -5917,7 +5920,7 @@ public class EmailProvider extends ContentProvider
// Clean up
AccountBackupRestore.backup(context);
SecurityPolicy.getInstance(context).reducePolicies();
MailActivityEmail.setServicesEnabledSync(context);
setServicesEnabledSync(context);
// TODO: We ought to reconcile accounts here, but some callers do this in a loop,
// which would be a problem when the first account reconciliation shuts us down.
return 1;
@ -6185,4 +6188,90 @@ public class EmailProvider extends ContentProvider
notifyUI(UIPROVIDER_ALL_ACCOUNTS_NOTIFIER, null);
}
}
/**
* Asynchronous version of {@link #setServicesEnabledSync(Context)}. Use when calling from
* UI thread (or lifecycle entry points.)
*/
public static void setServicesEnabledAsync(final Context context) {
if (context.getResources().getBoolean(R.bool.enable_services)) {
EmailAsyncTask.runAsyncParallel(new Runnable() {
@Override
public void run() {
setServicesEnabledSync(context);
}
});
}
}
/**
* Called throughout the application when the number of accounts has changed. This method
* enables or disables the Compose activity, the boot receiver and the service based on
* whether any accounts are configured.
*
* Blocking call - do not call from UI/lifecycle threads.
*
* @return true if there are any accounts configured.
*/
public static boolean setServicesEnabledSync(Context context) {
// Make sure we're initialized
EmailContent.init(context);
Cursor c = null;
try {
c = context.getContentResolver().query(
Account.CONTENT_URI,
Account.ID_PROJECTION,
null, null, null);
boolean enable = c != null && c.getCount() > 0;
setServicesEnabled(context, enable);
return enable;
} finally {
if (c != null) {
c.close();
}
}
}
private static void setServicesEnabled(Context context, boolean enabled) {
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(
new ComponentName(context, AttachmentService.class),
enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
// Start/stop the various services depending on whether there are any accounts
// TODO: Make sure that the AttachmentService responds to this request as it
// expects a particular set of data in the intents that it receives or it ignores.
startOrStopService(enabled, context, new Intent(context, AttachmentService.class));
final NotificationController controller =
NotificationControllerCreatorHolder.getInstance(context);
if (controller != null) {
controller.watchForMessages();
}
}
/**
* Starts or stops the service as necessary.
* @param enabled If {@code true}, the service will be started. Otherwise, it will be stopped.
* @param context The context to manage the service with.
* @param intent The intent of the service to be managed.
*/
private static void startOrStopService(boolean enabled, Context context, Intent intent) {
if (enabled) {
context.startService(intent);
} else {
context.stopService(intent);
}
}
public static Uri getIncomingSettingsUri(long accountId) {
final Uri.Builder baseUri = Uri.parse("auth://" + EmailContent.EMAIL_PACKAGE_NAME +
".ACCOUNT_SETTINGS/incoming/").buildUpon();
IntentUtilities.setAccountId(baseUri, accountId);
return baseUri.build();
}
}

View File

@ -34,6 +34,7 @@ import android.text.format.DateUtils;
import com.android.email.AttachmentInfo;
import com.android.email.EmailConnectivityManager;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.NotificationController;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
@ -1133,8 +1134,11 @@ public class AttachmentService extends Service implements Runnable {
// message never get sent
EmailContent.delete(this, Attachment.CONTENT_URI, attachment.mId);
// TODO: Talk to UX about whether this is even worth doing
NotificationController nc = NotificationController.getInstance(this);
nc.showDownloadForwardFailedNotificationSynchronous(attachment);
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(this);
if (nc != null) {
nc.showDownloadForwardFailedNotificationSynchronous(attachment);
}
deleted = true;
LogUtils.w(LOG_TAG, "Deleting forwarded attachment #%d for message #%d",
attachmentId, attachment.mMessageKey);

View File

@ -16,8 +16,8 @@
package com.android.email.service;
import com.android.email.activity.setup.AccountSetupFinal;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.EmailContent;
import android.accounts.AbstractAccountAuthenticator;
@ -109,8 +109,8 @@ public class AuthenticatorService extends Service {
} else {
Bundle b = new Bundle();
Intent intent =
AccountSetupFinal.actionGetCreateAccountIntent(AuthenticatorService.this,
accountType);
AuthenticatorSetupIntentHelper.actionGetCreateAccountIntent(
AuthenticatorService.this, accountType);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
b.putParcelable(AccountManager.KEY_INTENT, intent);
return b;

View File

@ -27,7 +27,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import com.android.email.activity.setup.AccountSetupFinal;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
/**
* Anauthenticator service for reconciliation tests; it simply adds the account to AccountManager
@ -67,8 +67,8 @@ public class EasTestAuthenticatorService extends Service {
} else {
Bundle b = new Bundle();
Intent intent =
AccountSetupFinal.actionGetCreateAccountIntent(
EasTestAuthenticatorService.this, accountType);
AuthenticatorSetupIntentHelper.actionGetCreateAccountIntent(
EasTestAuthenticatorService.this, accountType);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
b.putParcelable(AccountManager.KEY_INTENT, intent);
return b;

View File

@ -27,6 +27,7 @@ import android.os.RemoteException;
import com.android.email.DebugUtils;
import com.android.email.NotificationController;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.mail.Sender;
import com.android.email.mail.Store;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
@ -424,7 +425,8 @@ public abstract class EmailServiceStub extends IEmailService.Stub implements IEm
return;
}
TrafficStats.setThreadStatsTag(TrafficFlags.getSmtpFlags(context, account));
final NotificationController nc = NotificationController.getInstance(context);
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
// 1. Loop through all messages in the account's outbox
final long outboxId = Mailbox.findMailboxOfType(context, account.mId, Mailbox.TYPE_OUTBOX);
if (outboxId == Mailbox.NO_MAILBOX) {
@ -471,7 +473,7 @@ public abstract class EmailServiceStub extends IEmailService.Stub implements IEm
sender.sendMessage(messageId);
} catch (MessagingException me) {
// report error for this message, but keep trying others
if (me instanceof AuthenticationFailedException) {
if (me instanceof AuthenticationFailedException && nc != null) {
nc.showLoginFailedNotificationSynchronous(account.mId,
false /* incoming */);
}
@ -507,9 +509,11 @@ public abstract class EmailServiceStub extends IEmailService.Stub implements IEm
resolver.delete(syncedUri, null, null);
}
}
nc.cancelLoginFailedNotification(account.mId);
if (nc != null) {
nc.cancelLoginFailedNotification(account.mId);
}
} catch (MessagingException me) {
if (me instanceof AuthenticationFailedException) {
if (me instanceof AuthenticationFailedException && nc != null) {
nc.showLoginFailedNotificationSynchronous(account.mId, false /* incoming */);
}
} finally {

View File

@ -33,6 +33,7 @@ import android.text.format.DateUtils;
import com.android.email.DebugUtils;
import com.android.email.LegacyConversions;
import com.android.email.NotificationController;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.R;
import com.android.email.mail.Store;
import com.android.email.provider.Utilities;
@ -164,7 +165,8 @@ public class ImapService extends Service {
final Account account, final Mailbox folder, final boolean loadMore,
final boolean uiRefresh) throws MessagingException {
TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(context, account));
NotificationController nc = NotificationController.getInstance(context);
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
Store remoteStore = null;
try {
remoteStore = Store.getInstance(account, context);

View File

@ -30,6 +30,7 @@ import android.os.RemoteException;
import com.android.email.DebugUtils;
import com.android.email.NotificationController;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.mail.Store;
import com.android.email.mail.store.Pop3Store;
import com.android.email.mail.store.Pop3Store.Pop3Folder;
@ -107,16 +108,19 @@ public class Pop3Service extends Service {
public static int synchronizeMailboxSynchronous(Context context, final Account account,
final Mailbox folder, final int deltaMessageCount) throws MessagingException {
TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(context, account));
NotificationController nc = NotificationController.getInstance(context);
final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
try {
synchronizePop3Mailbox(context, account, folder, deltaMessageCount);
// Clear authentication notification for this account
nc.cancelLoginFailedNotification(account.mId);
if (nc != null) {
nc.cancelLoginFailedNotification(account.mId);
}
} catch (MessagingException e) {
if (Logging.LOGD) {
LogUtils.v(Logging.LOG_TAG, "synchronizeMailbox", e);
}
if (e instanceof AuthenticationFailedException) {
if (e instanceof AuthenticationFailedException && nc != null) {
// Generate authentication notification
nc.showLoginFailedNotificationSynchronous(account.mId, true /* incoming */);
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2014 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.setup;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
public class AuthenticatorSetupIntentHelper {
// NORMAL is the standard entry from the Email app; EAS and POP_IMAP are used when entering via
// Settings -> Accounts
public static final int FLOW_MODE_UNSPECIFIED = -1;
public static final int FLOW_MODE_NORMAL = 0;
public static final int FLOW_MODE_ACCOUNT_MANAGER = 1;
public static final int FLOW_MODE_EDIT = 3;
public static final int FLOW_MODE_FORCE_CREATE = 4;
public static final int FLOW_MODE_NO_ACCOUNTS = 8;
public static final String EXTRA_FLOW_MODE = "FLOW_MODE";
public static final String EXTRA_FLOW_ACCOUNT_TYPE = "FLOW_ACCOUNT_TYPE";
public static Intent actionNewAccountIntent(final Context context) {
final Intent i = new Intent();
i.setComponent(
new ComponentName(context, "com.android.email.activity.setup.AccountSetupFinal"));
i.putExtra(EXTRA_FLOW_MODE, FLOW_MODE_NORMAL);
return i;
}
public static Intent actionNewAccountWithResultIntent(final Context context) {
final Intent i = new Intent();
i.setComponent(
new ComponentName(context, "com.android.email.activity.setup.AccountSetupFinal"));
i.putExtra(EXTRA_FLOW_MODE, FLOW_MODE_NO_ACCOUNTS);
return i;
}
public static Intent actionGetCreateAccountIntent(
final Context context, final String accountManagerType) {
final Intent i = new Intent();
i.setComponent(
new ComponentName(context, "com.android.email.activity.setup.AccountSetupFinal"));
i.putExtra(EXTRA_FLOW_MODE, FLOW_MODE_ACCOUNT_MANAGER);
i.putExtra(EXTRA_FLOW_ACCOUNT_TYPE, accountManagerType);
return i;
}
}

View File

@ -62,5 +62,13 @@ public class EmailApplication extends Application {
});
PublicPreferenceActivity.sPreferenceActivityClass = EmailPreferenceActivity.class;
NotificationControllerCreatorHolder.setNotificationControllerCreator(
new NotificationControllerCreator() {
@Override
public NotificationController getInstance(Context context){
return EmailNotificationController.getInstance(context);
}
});
}
}

View File

@ -62,7 +62,7 @@ import java.util.Set;
/**
* Class that manages notifications.
*/
public class NotificationController {
public class EmailNotificationController implements NotificationController {
private static final String LOG_TAG = LogTag.getLogTag();
private static final int NOTIFICATION_ID_ATTACHMENT_WARNING = 3;
@ -76,7 +76,7 @@ public class NotificationController {
private static NotificationThread sNotificationThread;
private static Handler sNotificationHandler;
private static NotificationController sInstance;
private static EmailNotificationController sInstance;
private final Context mContext;
private final NotificationManager mNotificationManager;
private final Clock mClock;
@ -86,7 +86,7 @@ public class NotificationController {
private ContentObserver mAccountObserver;
/** Constructor */
protected NotificationController(Context context, Clock clock) {
protected EmailNotificationController(Context context, Clock clock) {
mContext = context.getApplicationContext();
EmailContent.init(context);
mNotificationManager = (NotificationManager) context.getSystemService(
@ -95,9 +95,9 @@ public class NotificationController {
}
/** Singleton access */
public static synchronized NotificationController getInstance(Context context) {
public static synchronized EmailNotificationController getInstance(Context context) {
if (sInstance == null) {
sInstance = new NotificationController(context, Clock.INSTANCE);
sInstance = new EmailNotificationController(context, Clock.INSTANCE);
}
return sInstance;
}
@ -182,6 +182,7 @@ public class NotificationController {
* notification shown to the user. And, when we start observing database changes, we restore
* the saved state.
*/
@Override
public void watchForMessages() {
ensureHandlerExists();
// Run this on the message notification handler
@ -386,6 +387,7 @@ public class NotificationController {
*
* NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/
@Override
public void showDownloadForwardFailedNotificationSynchronous(Attachment attachment) {
final Message message = Message.restoreMessageWithId(mContext, attachment.mMessageKey);
if (message == null) return;
@ -410,6 +412,7 @@ public class NotificationController {
*
* NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/
@Override
public void showLoginFailedNotificationSynchronous(long accountId, boolean incoming) {
final Account account = Account.restoreAccountWithId(mContext, accountId);
if (account == null) return;
@ -420,7 +423,7 @@ public class NotificationController {
final Intent settingsIntent;
if (incoming) {
settingsIntent = new Intent(Intent.ACTION_VIEW,
HeadlessAccountSettingsLoader.getIncomingSettingsUri(accountId));
EmailProvider.getIncomingSettingsUri(accountId));
} else {
settingsIntent = new Intent(Intent.ACTION_VIEW,
HeadlessAccountSettingsLoader.getOutgoingSettingsUri(accountId));
@ -436,6 +439,7 @@ public class NotificationController {
/**
* Cancels the login failed notification for the given account.
*/
@Override
public void cancelLoginFailedNotification(long accountId) {
mNotificationManager.cancel(getLoginFailedNotificationId(accountId));
}
@ -446,6 +450,7 @@ public class NotificationController {
*
* NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/
@Override
public void showPasswordExpiringNotificationSynchronous(long accountId) {
final Account account = Account.restoreAccountWithId(mContext, accountId);
if (account == null) return;
@ -466,6 +471,7 @@ public class NotificationController {
*
* NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/
@Override
public void showPasswordExpiredNotificationSynchronous(long accountId) {
final Account account = Account.restoreAccountWithId(mContext, accountId);
if (account == null) return;
@ -482,6 +488,7 @@ public class NotificationController {
/**
* Cancels any password expire notifications [both expired & expiring].
*/
@Override
public void cancelPasswordExpirationNotifications() {
mNotificationManager.cancel(NOTIFICATION_ID_PASSWORD_EXPIRING);
mNotificationManager.cancel(NOTIFICATION_ID_PASSWORD_EXPIRED);
@ -491,6 +498,7 @@ public class NotificationController {
* Show (or update) a security needed notification. If tapped, the user is taken to a
* dialog asking whether he wants to update his settings.
*/
@Override
public void showSecurityNeededNotification(Account account) {
Intent intent = AccountSecurity.actionUpdateSecurityIntent(mContext, account.mId, true);
String accountName = account.getDisplayName();
@ -505,9 +513,10 @@ public class NotificationController {
* Show (or update) a security changed notification. If tapped, the user is taken to the
* account settings screen where he can view the list of enforced policies
*/
@Override
public void showSecurityChangedNotification(Account account) {
final Intent intent = new Intent(Intent.ACTION_VIEW,
HeadlessAccountSettingsLoader.getIncomingSettingsUri(account.getId()));
EmailProvider.getIncomingSettingsUri(account.getId()));
final String accountName = account.getDisplayName();
final String ticker =
mContext.getString(R.string.security_changed_ticker_fmt, accountName);
@ -521,9 +530,10 @@ public class NotificationController {
* Show (or update) a security unsupported notification. If tapped, the user is taken to the
* account settings screen where he can view the list of unsupported policies
*/
@Override
public void showSecurityUnsupportedNotification(Account account) {
final Intent intent = new Intent(Intent.ACTION_VIEW,
HeadlessAccountSettingsLoader.getIncomingSettingsUri(account.getId()));
EmailProvider.getIncomingSettingsUri(account.getId()));
final String accountName = account.getDisplayName();
final String ticker =
mContext.getString(R.string.security_unsupported_ticker_fmt, accountName);
@ -536,6 +546,7 @@ public class NotificationController {
/**
* Cancels all security needed notifications.
*/
@Override
public void cancelSecurityNeededNotification() {
EmailAsyncTask.runAsyncParallel(new Runnable() {
@Override
@ -559,7 +570,8 @@ public class NotificationController {
* Cancels all notifications for the specified account id. This includes new mail notifications,
* as well as special login/security notifications.
*/
public static void cancelNotifications(final Context context, final Account account) {
@Override
public void cancelNotifications(final Context context, final Account account) {
final EmailServiceUtils.EmailServiceInfo serviceInfo
= EmailServiceUtils.getServiceInfoForAccount(context, account.mId);
if (serviceInfo == null) {
@ -646,7 +658,8 @@ public class NotificationController {
}
}
public static void handleUpdateNotificationIntent(Context context, Intent intent) {
@Override
public void handleUpdateNotificationIntent(Context context, Intent intent) {
final Uri accountUri =
intent.getParcelableExtra(UIProvider.UpdateNotificationExtras.EXTRA_ACCOUNT);
final Uri folderUri =

View File

@ -28,6 +28,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import com.android.email.provider.EmailProvider;
import com.android.email.service.EmailServiceUtils;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.provider.Account;
@ -298,7 +299,7 @@ public class AccountCreationFragment extends Fragment {
account.mFlags &= ~Account.FLAGS_SECURITY_HOLD;
AccountSettingsUtils.commitSettings(mAppContext, account);
// Start up services based on new account(s)
MailActivityEmail.setServicesEnabledSync(mAppContext);
EmailProvider.setServicesEnabledSync(mAppContext);
EmailServiceUtils
.startService(mAppContext, account.mHostAuthRecv.mProtocol);
return account;

View File

@ -26,6 +26,7 @@ import android.content.Intent;
import android.os.Bundle;
import com.android.email.R;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.Account;
import com.android.mail.utils.LogUtils;
@ -65,7 +66,7 @@ public class AccountServerSettingsActivity extends AccountSetupActivity implemen
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSetupData.setFlowMode(SetupDataFragment.FLOW_MODE_EDIT);
mSetupData.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_EDIT);
setContentView(R.layout.account_server_settings);
setFinishOnTouchOutside(false);

View File

@ -52,7 +52,6 @@ import com.android.email.provider.EmailProvider;
import com.android.email.provider.FolderPickerActivity;
import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
@ -402,7 +401,7 @@ public class AccountSettingsFragment extends MailAccountPrefsFragment
}
if (cv.size() > 0) {
new UpdateTask().run(mContext.getContentResolver(), mAccount.getUri(), cv, null, null);
MailActivityEmail.setServicesEnabledAsync(mContext);
EmailProvider.setServicesEnabledAsync(mContext);
}
return false;
}

View File

@ -43,6 +43,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import com.android.email.R;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.email.service.EmailServiceUtils;
import com.android.emailcommon.VendorPolicyLoader;
import com.android.emailcommon.provider.Account;
@ -97,8 +98,6 @@ public class AccountSetupFinal extends AccountSetupActivity
* and the appropriate incoming/outgoing information will be filled in automatically.
*/
private static String INTENT_FORCE_CREATE_ACCOUNT;
private static final String EXTRA_FLOW_MODE = "FLOW_MODE";
private static final String EXTRA_FLOW_ACCOUNT_TYPE = "FLOW_ACCOUNT_TYPE";
private static final String EXTRA_CREATE_ACCOUNT_EMAIL = "EMAIL";
private static final String EXTRA_CREATE_ACCOUNT_USER = "USER";
private static final String EXTRA_CREATE_ACCOUNT_PASSWORD = "PASSWORD";
@ -180,26 +179,6 @@ public class AccountSetupFinal extends AccountSetupActivity
private static final int EXISTING_ACCOUNTS_LOADER_ID = 1;
private Map<String, String> mExistingAccountsMap;
public static Intent actionNewAccountIntent(final Context context) {
final Intent i = new Intent(context, AccountSetupFinal.class);
i.putExtra(EXTRA_FLOW_MODE, SetupDataFragment.FLOW_MODE_NORMAL);
return i;
}
public static Intent actionNewAccountWithResultIntent(final Context context) {
final Intent i = new Intent(context, AccountSetupFinal.class);
i.putExtra(EXTRA_FLOW_MODE, SetupDataFragment.FLOW_MODE_NO_ACCOUNTS);
return i;
}
public static Intent actionGetCreateAccountIntent(final Context context,
final String accountManagerType) {
final Intent i = new Intent(context, AccountSetupFinal.class);
i.putExtra(EXTRA_FLOW_MODE, SetupDataFragment.FLOW_MODE_ACCOUNT_MANAGER);
i.putExtra(EXTRA_FLOW_ACCOUNT_TYPE, accountManagerType);
return i;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -250,11 +229,13 @@ public class AccountSetupFinal extends AccountSetupActivity
// Initialize the SetupDataFragment
if (INTENT_FORCE_CREATE_ACCOUNT.equals(action)) {
mSetupData.setFlowMode(SetupDataFragment.FLOW_MODE_FORCE_CREATE);
mSetupData.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE);
} else {
final int intentFlowMode = intent.getIntExtra(EXTRA_FLOW_MODE,
SetupDataFragment.FLOW_MODE_UNSPECIFIED);
final String flowAccountType = intent.getStringExtra(EXTRA_FLOW_ACCOUNT_TYPE);
final int intentFlowMode = intent.getIntExtra(
AuthenticatorSetupIntentHelper.EXTRA_FLOW_MODE,
AuthenticatorSetupIntentHelper.FLOW_MODE_UNSPECIFIED);
final String flowAccountType = intent.getStringExtra(
AuthenticatorSetupIntentHelper.EXTRA_FLOW_ACCOUNT_TYPE);
mSetupData.setAmProtocol(
EmailServiceUtils.getProtocolFromAccountType(this, flowAccountType));
mSetupData.setFlowMode(intentFlowMode);
@ -273,8 +254,8 @@ public class AccountSetupFinal extends AccountSetupActivity
mPasswordFailed = false;
}
if (!mIsProcessing
&& mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
if (!mIsProcessing && mSetupData.getFlowMode() ==
AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE) {
/**
* To support continuous testing, we allow the forced creation of accounts.
* This works in a manner fairly similar to automatic setup, in which the complete
@ -679,7 +660,8 @@ public class AccountSetupFinal extends AccountSetupActivity
case STATE_CREATING:
mState = STATE_NAMES;
updateContentFragment(true /* addToBackstack */);
if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
if (mSetupData.getFlowMode() ==
AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE) {
getFragmentManager().executePendingTransactions();
initiateAccountFinalize();
}

View File

@ -33,6 +33,7 @@ import android.widget.EditText;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.email.service.EmailServiceUtils;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.Account;
public class AccountSetupNamesFragment extends AccountSetupFragment {
@ -81,8 +82,8 @@ public class AccountSetupNamesFragment extends AccountSetupFragment {
final Account account = setupData.getAccount();
if (flowMode != SetupDataFragment.FLOW_MODE_FORCE_CREATE
&& flowMode != SetupDataFragment.FLOW_MODE_EDIT) {
if (flowMode != AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE
&& flowMode != AuthenticatorSetupIntentHelper.FLOW_MODE_EDIT) {
final String accountEmail = account.mEmailAddress;
mDescription.setText(accountEmail);
@ -99,8 +100,8 @@ public class AccountSetupNamesFragment extends AccountSetupFragment {
} else {
if (account.getSenderName() != null) {
mName.setText(account.getSenderName());
} else if (flowMode != SetupDataFragment.FLOW_MODE_FORCE_CREATE
&& flowMode != SetupDataFragment.FLOW_MODE_EDIT) {
} else if (flowMode != AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE
&& flowMode != AuthenticatorSetupIntentHelper.FLOW_MODE_EDIT) {
// Attempt to prefill the name field from the profile if we don't have it,
final Context loaderContext = getActivity().getApplicationContext();
getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() {

View File

@ -27,6 +27,7 @@ import android.view.Menu;
import android.view.MenuItem;
import com.android.email.R;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.utility.IntentUtilities;
import com.android.mail.providers.UIProvider.EditSettingsExtras;
import com.android.mail.ui.settings.MailPreferenceActivity;
@ -201,7 +202,7 @@ public class EmailPreferenceActivity extends MailPreferenceActivity {
}
private void onAddNewAccount() {
final Intent setupIntent = AccountSetupFinal.actionNewAccountIntent(this);
final Intent setupIntent = AuthenticatorSetupIntentHelper.actionNewAccountIntent(this);
startActivity(setupIntent);
}

View File

@ -21,13 +21,6 @@ import com.android.mail.ui.MailAsyncTaskLoader;
*/
public class HeadlessAccountSettingsLoader extends Activity {
public static Uri getIncomingSettingsUri(long accountId) {
final Uri.Builder baseUri = Uri.parse("auth://" + EmailContent.EMAIL_PACKAGE_NAME +
".ACCOUNT_SETTINGS/incoming/").buildUpon();
IntentUtilities.setAccountId(baseUri, accountId);
return baseUri.build();
}
public static Uri getOutgoingSettingsUri(long accountId) {
final Uri.Builder baseUri = Uri.parse("auth://" + EmailContent.EMAIL_PACKAGE_NAME +
".ACCOUNT_SETTINGS/outgoing/").buildUpon();

View File

@ -7,6 +7,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import com.android.email.service.EmailServiceUtils;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.provider.Policy;
@ -18,20 +19,12 @@ public class SetupDataFragment extends Fragment implements Parcelable {
// The "extra" name for the Bundle saved with SetupData
public static final String EXTRA_SETUP_DATA = "com.android.email.setupdata";
// NORMAL is the standard entry from the Email app; EAS and POP_IMAP are used when entering via
// Settings -> Accounts
public static final int FLOW_MODE_UNSPECIFIED = -1;
public static final int FLOW_MODE_NORMAL = 0;
public static final int FLOW_MODE_ACCOUNT_MANAGER = 1;
public static final int FLOW_MODE_EDIT = 3;
public static final int FLOW_MODE_FORCE_CREATE = 4;
// The following two modes are used to "pop the stack" and return from the setup flow. We
// either return to the caller (if we're in an account type flow) or go to the message list
// TODO: figure out if we still care about these
public static final int FLOW_MODE_RETURN_TO_CALLER = 5;
public static final int FLOW_MODE_RETURN_TO_MESSAGE_LIST = 6;
public static final int FLOW_MODE_RETURN_NO_ACCOUNTS_RESULT = 7;
public static final int FLOW_MODE_NO_ACCOUNTS = 8;
// Mode bits for AccountSetupCheckSettings, indicating the type of check requested
public static final int CHECK_INCOMING = 1;
@ -49,7 +42,7 @@ public class SetupDataFragment extends Fragment implements Parcelable {
private static final String SAVESTATE_AM_PROTOCOL = "SetupDataFragment.amProtocol";
// All access will be through getters/setters
private int mFlowMode = FLOW_MODE_NORMAL;
private int mFlowMode = AuthenticatorSetupIntentHelper.FLOW_MODE_NORMAL;
private Account mAccount;
private String mEmail;
private Bundle mCredentialResults;

View File

@ -26,21 +26,14 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import com.android.email.NotificationController;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.provider.EmailProvider;
import com.android.email.service.AttachmentService;
import com.android.email.service.EmailServiceUtils;
import com.android.emailcommon.Logging;
import com.android.emailcommon.TempDirectory;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.emailcommon.utility.EmailAsyncTask;
import com.android.emailcommon.utility.IntentUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.mail.providers.Folder;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogTag;
@ -62,78 +55,6 @@ public class MailActivityEmail extends com.android.mail.ui.MailActivity {
}
/**
* Asynchronous version of {@link #setServicesEnabledSync(Context)}. Use when calling from
* UI thread (or lifecycle entry points.)
*/
public static void setServicesEnabledAsync(final Context context) {
if (context.getResources().getBoolean(R.bool.enable_services)) {
EmailAsyncTask.runAsyncParallel(new Runnable() {
@Override
public void run() {
setServicesEnabledSync(context);
}
});
}
}
/**
* Called throughout the application when the number of accounts has changed. This method
* enables or disables the Compose activity, the boot receiver and the service based on
* whether any accounts are configured.
*
* Blocking call - do not call from UI/lifecycle threads.
*
* @return true if there are any accounts configured.
*/
public static boolean setServicesEnabledSync(Context context) {
// Make sure we're initialized
EmailContent.init(context);
Cursor c = null;
try {
c = context.getContentResolver().query(
Account.CONTENT_URI,
Account.ID_PROJECTION,
null, null, null);
boolean enable = c != null && c.getCount() > 0;
setServicesEnabled(context, enable);
return enable;
} finally {
if (c != null) {
c.close();
}
}
}
private static void setServicesEnabled(Context context, boolean enabled) {
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(
new ComponentName(context, AttachmentService.class),
enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
// Start/stop the various services depending on whether there are any accounts
// TODO: Make sure that the AttachmentService responds to this request as it
// expects a particular set of data in the intents that it receives or it ignores.
startOrStopService(enabled, context, new Intent(context, AttachmentService.class));
NotificationController.getInstance(context).watchForMessages();
}
/**
* Starts or stops the service as necessary.
* @param enabled If {@code true}, the service will be started. Otherwise, it will be stopped.
* @param context The context to manage the service with.
* @param intent The intent of the service to be managed.
*/
private static void startOrStopService(boolean enabled, Context context, Intent intent) {
if (enabled) {
context.startService(intent);
} else {
context.stopService(intent);
}
}
@Override
public void onCreate(Bundle bundle) {
final Intent intent = getIntent();
@ -163,7 +84,7 @@ public class MailActivityEmail extends com.android.mail.ui.MailActivity {
// Make sure all required services are running when the app is started (can prevent
// issues after an adb sync/install)
setServicesEnabledAsync(this);
EmailProvider.setServicesEnabledAsync(this);
}
/**

View File

@ -22,6 +22,7 @@ import android.net.Uri;
import com.android.email.R;
import com.android.email.activity.setup.AccountSetupFinal;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
public class EmailAccountCacheProvider extends MailAppProvider {
// Content provider for Email
@ -36,6 +37,6 @@ public class EmailAccountCacheProvider extends MailAppProvider {
@Override
protected Intent getNoAccountsIntent(Context context) {
return AccountSetupFinal.actionNewAccountWithResultIntent(context);
return AuthenticatorSetupIntentHelper.actionNewAccountWithResultIntent(context);
}
}

View File

@ -1,55 +0,0 @@
/*
* 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;
import android.content.Context;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.Suppress;
/**
* Test for {@link NotificationController}.
*
* TODO Add tests for all methods.
*/
@Suppress
public class NotificationControllerTest extends AndroidTestCase {
private Context mProviderContext;
private NotificationController mTarget;
private final MockClock mMockClock = new MockClock();
private int mRingerMode;
/**
* Subclass {@link NotificationController} to override un-mockable operations.
*/
protected class NotificationControllerForTest extends NotificationController {
NotificationControllerForTest(Context context) {
super(context, mMockClock);
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
mProviderContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext(mContext);
mTarget = new NotificationControllerForTest(mProviderContext);
}
// the ringtone and vibration flags are depracated and the method that we use
// to test notification has been removed in
// https://googleplex-android-review.googlesource.com/#/c/271237/
}

View File

@ -1,210 +0,0 @@
/*
* 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.activity;
import com.android.email.activity.ContactStatusLoader.Result;
import com.android.mail.utils.MatrixCursorWithCachedColumns;
import android.content.Context;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.StatusUpdates;
import android.test.ProviderTestCase2;
import android.test.mock.MockContentProvider;
import android.test.suitebuilder.annotation.SmallTest;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import junit.framework.Assert;
/**
* Test for {@link ContactStatusLoader}
*
* Unfortunately this doesn't check {@link ContactStatusLoader.Result#mLookupUri}, because we don't
* (shouldn't) know how {@link android.provider.ContactsContract.Data#getContactLookupUri} is
* implemented.
*/
@SmallTest
public class ContactStatusLoaderTest
extends ProviderTestCase2<ContactStatusLoaderTest.MockContactProvider> {
private static final String EMAIL = "a@b.c";
private MockContactProvider mProvider;
public ContactStatusLoaderTest() {
super(MockContactProvider.class, ContactsContract.AUTHORITY);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mProvider = getProvider();
}
// Contact doesn't exist
public void brokentestContactNotFound() {
// Insert empty cursor
mProvider.mCursors.offer(new MatrixCursorWithCachedColumns(
ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE));
// Load!
ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
Result r = l.loadInBackground();
// Check input to the provider
assertEquals(1, mProvider.mUris.size());
assertEquals("content://com.android.contacts/data/emails/lookup/a%40b.c",
mProvider.mUris.get(0));
// Check result
assertNull(r.mPhoto);
assertEquals(ContactStatusLoader.PRESENCE_UNKNOWN_RESOURCE_ID, r.mPresenceResId);
}
// Contact doesn't exist -- provider returns null for the first query
public void brokentestNull() {
// No cursor prepared. (Mock provider will return null)
// Load!
ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
Result r = l.loadInBackground();
// Check result
assertNull(r.mPhoto);
assertEquals(ContactStatusLoader.PRESENCE_UNKNOWN_RESOURCE_ID, r.mPresenceResId);
}
// Contact exists, but no photo
public void brokentestNoPhoto() {
// Result for the first query (the one for photo-id)
MatrixCursor cursor1 =
new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
mProvider.mCursors.offer(cursor1);
// Empty cursor for the second query
mProvider.mCursors.offer(
new MatrixCursorWithCachedColumns(ContactStatusLoader.PHOTO_PROJECTION));
// Load!
ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
Result r = l.loadInBackground();
// Check input to the provider
// We should have had at least two queries from loadInBackground.
// There can be extra queries from getContactLookupUri(), but this test shouldn't know
// the details, so use ">= 2".
assertTrue(mProvider.mUris.size() >= 2);
assertEquals("content://com.android.contacts/data/emails/lookup/a%40b.c",
mProvider.mUris.get(0));
assertEquals("content://com.android.contacts/data/12345",
mProvider.mUris.get(1));
// Check result
assertNull(r.mPhoto); // no photo
assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
}
// Contact exists, but no photo (provider returns null for the second query)
public void brokentestNull2() {
// Result for the first query (the one for photo-id)
MatrixCursor cursor1 =
new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
mProvider.mCursors.offer(cursor1);
// No cursor for the second query
// Load!
ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
Result r = l.loadInBackground();
// Check result
assertNull(r.mPhoto); // no photo
assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
}
// Contact exists, with a photo
public void brokentestWithPhoto() {
// Result for the first query (the one for photo-id)
MatrixCursor cursor1 =
new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
mProvider.mCursors.offer(cursor1);
// Prepare for the second query.
MatrixCursor cursor2 = new PhotoCursor(createJpegData(10, 20));
mProvider.mCursors.offer(cursor2);
// Load!
ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
Result r = l.loadInBackground();
// Check result
assertNotNull(r.mPhoto);
assertEquals(10, r.mPhoto.getWidth());
assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
}
private static byte[] createJpegData(int width, int height) {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, out);
return out.toByteArray();
}
// MatrixCursor doesn't support getBlob, so use this...
private static class PhotoCursor extends MatrixCursorWithCachedColumns {
private final byte[] mBlob;
public PhotoCursor(byte[] blob) {
super(ContactStatusLoader.PHOTO_PROJECTION);
mBlob = blob;
addRow(new Object[] {null}); // Add dummy row
}
@Override
public byte[] getBlob(int column) {
Assert.assertEquals(0, column);
return mBlob;
}
}
public static class MockContactProvider extends MockContentProvider {
public ArrayList<String> mUris = new ArrayList<String>();
public final Queue<Cursor> mCursors = new LinkedBlockingQueue<Cursor>();
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
mUris.add(uri.toString());
return mCursors.poll();
}
@Override
public void attachInfo(Context context, ProviderInfo info) {
}
}
}

View File

@ -26,6 +26,7 @@ import android.view.View;
import android.widget.EditText;
import com.android.email.R;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
@ -198,7 +199,7 @@ public class AccountSetupIncomingTests extends
auth.setHostAuthFromString(storeUriString);
final SetupDataFragment setupDataFragment =
new SetupDataFragment();
setupDataFragment.setFlowMode(SetupDataFragment.FLOW_MODE_NORMAL);
setupDataFragment.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_NORMAL);
setupDataFragment.setAccount(account);
final Intent i = new Intent(AccountSetupFinal.ACTION_JUMP_TO_INCOMING);
i.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupDataFragment);

View File

@ -27,6 +27,7 @@ import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import com.android.email.R;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
@ -173,7 +174,7 @@ public class AccountSetupOptionsTests
auth.setHostAuthFromString(storeUri);
final SetupDataFragment setupDataFragment =
new SetupDataFragment();
setupDataFragment.setFlowMode(SetupDataFragment.FLOW_MODE_NORMAL);
setupDataFragment.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_NORMAL);
setupDataFragment.setAccount(account);
final Intent i = new Intent(AccountSetupFinal.ACTION_JUMP_TO_OPTIONS);
i.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupDataFragment);

View File

@ -26,6 +26,7 @@ import android.widget.CheckBox;
import android.widget.EditText;
import com.android.email.R;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
@ -203,7 +204,7 @@ public class AccountSetupOutgoingTests extends
auth.setHostAuthFromString(senderUriString);
final SetupDataFragment setupDataFragment =
new SetupDataFragment();
setupDataFragment.setFlowMode(SetupDataFragment.FLOW_MODE_NORMAL);
setupDataFragment.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_NORMAL);
setupDataFragment.setAccount(account);
final Intent i = new Intent(AccountSetupFinal.ACTION_JUMP_TO_OUTGOING);
i.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupDataFragment);