Changes to support smaller email tombstone apk size

This reduces the tombstone down by 100K

A follow-on cl will remove the unused resources from the tombstone build

Bug: 17414014
Change-Id: I5d38811b17a5273ec726e750ab123e10e36cee04
This commit is contained in:
Paul Westbrook 2014-09-07 13:36:33 -07:00
parent 88929fd2bc
commit bb68c13afa
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, $(unified_email_dir)/src)
LOCAL_SRC_FILES += $(call all-java-files-under, src/com/android) 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_SRC_FILES += $(call all-java-files-under, src/com/beetstra)
LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dir)) LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dir))

View File

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

View File

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

View File

@ -33,6 +33,7 @@ import android.content.PeriodicSync;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.UriMatcher; import android.content.UriMatcher;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.ContentObserver; import android.database.ContentObserver;
@ -66,15 +67,14 @@ import com.android.common.content.ProjectionMap;
import com.android.email.DebugUtils; import com.android.email.DebugUtils;
import com.android.email.Preferences; import com.android.email.Preferences;
import com.android.email.R; import com.android.email.R;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.NotificationController;
import com.android.email.SecurityPolicy; import com.android.email.SecurityPolicy;
import com.android.email.activity.setup.AccountSecurity; 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.AccountSettingsUtils;
import com.android.email.activity.setup.HeadlessAccountSettingsLoader;
import com.android.email.service.AttachmentService; import com.android.email.service.AttachmentService;
import com.android.email.service.EmailServiceUtils; import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo; import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.Logging; import com.android.emailcommon.Logging;
import com.android.emailcommon.mail.Address; import com.android.emailcommon.mail.Address;
import com.android.emailcommon.provider.Account; 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.service.SearchParams;
import com.android.emailcommon.utility.AttachmentUtilities; import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.emailcommon.utility.EmailAsyncTask; import com.android.emailcommon.utility.EmailAsyncTask;
import com.android.emailcommon.utility.IntentUtilities;
import com.android.emailcommon.utility.Utility; import com.android.emailcommon.utility.Utility;
import com.android.ex.photo.provider.PhotoContract; import com.android.ex.photo.provider.PhotoContract;
import com.android.mail.preferences.MailPrefs; 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 BACKUP_DATABASE_NAME = "EmailProviderBackup.db";
private static final String ACCOUNT_MANAGER_JSON_TAG = "accountJson"; 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 * 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 * {@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); init(context);
DebugUtils.init(context); DebugUtils.init(context);
// Do this last, so that EmailContent/EmailProvider are initialized // Do this last, so that EmailContent/EmailProvider are initialized
MailActivityEmail.setServicesEnabledAsync(context); setServicesEnabledAsync(context);
reconcileAccountsAsync(context); reconcileAccountsAsync(context);
// Update widgets // Update widgets
@ -3439,8 +3443,7 @@ public class EmailProvider extends ContentProvider
} }
if (projectionColumns.contains(UIProvider.AccountColumns.REAUTHENTICATION_INTENT_URI)) { if (projectionColumns.contains(UIProvider.AccountColumns.REAUTHENTICATION_INTENT_URI)) {
values.put(UIProvider.AccountColumns.REAUTHENTICATION_INTENT_URI, values.put(UIProvider.AccountColumns.REAUTHENTICATION_INTENT_URI,
HeadlessAccountSettingsLoader.getIncomingSettingsUri(accountId) getIncomingSettingsUri(accountId).toString());
.toString());
} }
if (projectionColumns.contains(UIProvider.AccountColumns.MIME_TYPE)) { if (projectionColumns.contains(UIProvider.AccountColumns.MIME_TYPE)) {
values.put(UIProvider.AccountColumns.MIME_TYPE, EMAIL_APP_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)) { if (projectionColumns.contains(UIProvider.AccountColumns.SETTINGS_FRAGMENT_CLASS)) {
values.put(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)) { if (projectionColumns.contains(UIProvider.AccountColumns.SettingsColumns.REPLY_BEHAVIOR)) {
values.put(UIProvider.AccountColumns.SettingsColumns.REPLY_BEHAVIOR, values.put(UIProvider.AccountColumns.SettingsColumns.REPLY_BEHAVIOR,
@ -5917,7 +5920,7 @@ public class EmailProvider extends ContentProvider
// Clean up // Clean up
AccountBackupRestore.backup(context); AccountBackupRestore.backup(context);
SecurityPolicy.getInstance(context).reducePolicies(); SecurityPolicy.getInstance(context).reducePolicies();
MailActivityEmail.setServicesEnabledSync(context); setServicesEnabledSync(context);
// TODO: We ought to reconcile accounts here, but some callers do this in a loop, // 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. // which would be a problem when the first account reconciliation shuts us down.
return 1; return 1;
@ -6185,4 +6188,90 @@ public class EmailProvider extends ContentProvider
notifyUI(UIPROVIDER_ALL_ACCOUNTS_NOTIFIER, null); 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.AttachmentInfo;
import com.android.email.EmailConnectivityManager; import com.android.email.EmailConnectivityManager;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.NotificationController; import com.android.email.NotificationController;
import com.android.emailcommon.provider.Account; import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent; import com.android.emailcommon.provider.EmailContent;
@ -1133,8 +1134,11 @@ public class AttachmentService extends Service implements Runnable {
// message never get sent // message never get sent
EmailContent.delete(this, Attachment.CONTENT_URI, attachment.mId); EmailContent.delete(this, Attachment.CONTENT_URI, attachment.mId);
// TODO: Talk to UX about whether this is even worth doing // TODO: Talk to UX about whether this is even worth doing
NotificationController nc = NotificationController.getInstance(this); final NotificationController nc =
nc.showDownloadForwardFailedNotificationSynchronous(attachment); NotificationControllerCreatorHolder.getInstance(this);
if (nc != null) {
nc.showDownloadForwardFailedNotificationSynchronous(attachment);
}
deleted = true; deleted = true;
LogUtils.w(LOG_TAG, "Deleting forwarded attachment #%d for message #%d", LogUtils.w(LOG_TAG, "Deleting forwarded attachment #%d for message #%d",
attachmentId, attachment.mMessageKey); attachmentId, attachment.mMessageKey);

View File

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

View File

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

View File

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

View File

@ -33,6 +33,7 @@ import android.text.format.DateUtils;
import com.android.email.DebugUtils; import com.android.email.DebugUtils;
import com.android.email.LegacyConversions; import com.android.email.LegacyConversions;
import com.android.email.NotificationController; import com.android.email.NotificationController;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.R; import com.android.email.R;
import com.android.email.mail.Store; import com.android.email.mail.Store;
import com.android.email.provider.Utilities; 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 Account account, final Mailbox folder, final boolean loadMore,
final boolean uiRefresh) throws MessagingException { final boolean uiRefresh) throws MessagingException {
TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(context, account)); TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(context, account));
NotificationController nc = NotificationController.getInstance(context); final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
Store remoteStore = null; Store remoteStore = null;
try { try {
remoteStore = Store.getInstance(account, context); remoteStore = Store.getInstance(account, context);

View File

@ -30,6 +30,7 @@ import android.os.RemoteException;
import com.android.email.DebugUtils; import com.android.email.DebugUtils;
import com.android.email.NotificationController; import com.android.email.NotificationController;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.mail.Store; import com.android.email.mail.Store;
import com.android.email.mail.store.Pop3Store; import com.android.email.mail.store.Pop3Store;
import com.android.email.mail.store.Pop3Store.Pop3Folder; 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, public static int synchronizeMailboxSynchronous(Context context, final Account account,
final Mailbox folder, final int deltaMessageCount) throws MessagingException { final Mailbox folder, final int deltaMessageCount) throws MessagingException {
TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(context, account)); TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(context, account));
NotificationController nc = NotificationController.getInstance(context); final NotificationController nc =
NotificationControllerCreatorHolder.getInstance(context);
try { try {
synchronizePop3Mailbox(context, account, folder, deltaMessageCount); synchronizePop3Mailbox(context, account, folder, deltaMessageCount);
// Clear authentication notification for this account // Clear authentication notification for this account
nc.cancelLoginFailedNotification(account.mId); if (nc != null) {
nc.cancelLoginFailedNotification(account.mId);
}
} catch (MessagingException e) { } catch (MessagingException e) {
if (Logging.LOGD) { if (Logging.LOGD) {
LogUtils.v(Logging.LOG_TAG, "synchronizeMailbox", e); LogUtils.v(Logging.LOG_TAG, "synchronizeMailbox", e);
} }
if (e instanceof AuthenticationFailedException) { if (e instanceof AuthenticationFailedException && nc != null) {
// Generate authentication notification // Generate authentication notification
nc.showLoginFailedNotificationSynchronous(account.mId, true /* incoming */); 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; 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. * Class that manages notifications.
*/ */
public class NotificationController { public class EmailNotificationController implements NotificationController {
private static final String LOG_TAG = LogTag.getLogTag(); private static final String LOG_TAG = LogTag.getLogTag();
private static final int NOTIFICATION_ID_ATTACHMENT_WARNING = 3; private static final int NOTIFICATION_ID_ATTACHMENT_WARNING = 3;
@ -76,7 +76,7 @@ public class NotificationController {
private static NotificationThread sNotificationThread; private static NotificationThread sNotificationThread;
private static Handler sNotificationHandler; private static Handler sNotificationHandler;
private static NotificationController sInstance; private static EmailNotificationController sInstance;
private final Context mContext; private final Context mContext;
private final NotificationManager mNotificationManager; private final NotificationManager mNotificationManager;
private final Clock mClock; private final Clock mClock;
@ -86,7 +86,7 @@ public class NotificationController {
private ContentObserver mAccountObserver; private ContentObserver mAccountObserver;
/** Constructor */ /** Constructor */
protected NotificationController(Context context, Clock clock) { protected EmailNotificationController(Context context, Clock clock) {
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
EmailContent.init(context); EmailContent.init(context);
mNotificationManager = (NotificationManager) context.getSystemService( mNotificationManager = (NotificationManager) context.getSystemService(
@ -95,9 +95,9 @@ public class NotificationController {
} }
/** Singleton access */ /** Singleton access */
public static synchronized NotificationController getInstance(Context context) { public static synchronized EmailNotificationController getInstance(Context context) {
if (sInstance == null) { if (sInstance == null) {
sInstance = new NotificationController(context, Clock.INSTANCE); sInstance = new EmailNotificationController(context, Clock.INSTANCE);
} }
return sInstance; return sInstance;
} }
@ -182,6 +182,7 @@ public class NotificationController {
* notification shown to the user. And, when we start observing database changes, we restore * notification shown to the user. And, when we start observing database changes, we restore
* the saved state. * the saved state.
*/ */
@Override
public void watchForMessages() { public void watchForMessages() {
ensureHandlerExists(); ensureHandlerExists();
// Run this on the message notification handler // 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) * NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/ */
@Override
public void showDownloadForwardFailedNotificationSynchronous(Attachment attachment) { public void showDownloadForwardFailedNotificationSynchronous(Attachment attachment) {
final Message message = Message.restoreMessageWithId(mContext, attachment.mMessageKey); final Message message = Message.restoreMessageWithId(mContext, attachment.mMessageKey);
if (message == null) return; if (message == null) return;
@ -410,6 +412,7 @@ public class NotificationController {
* *
* NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS) * NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/ */
@Override
public void showLoginFailedNotificationSynchronous(long accountId, boolean incoming) { public void showLoginFailedNotificationSynchronous(long accountId, boolean incoming) {
final Account account = Account.restoreAccountWithId(mContext, accountId); final Account account = Account.restoreAccountWithId(mContext, accountId);
if (account == null) return; if (account == null) return;
@ -420,7 +423,7 @@ public class NotificationController {
final Intent settingsIntent; final Intent settingsIntent;
if (incoming) { if (incoming) {
settingsIntent = new Intent(Intent.ACTION_VIEW, settingsIntent = new Intent(Intent.ACTION_VIEW,
HeadlessAccountSettingsLoader.getIncomingSettingsUri(accountId)); EmailProvider.getIncomingSettingsUri(accountId));
} else { } else {
settingsIntent = new Intent(Intent.ACTION_VIEW, settingsIntent = new Intent(Intent.ACTION_VIEW,
HeadlessAccountSettingsLoader.getOutgoingSettingsUri(accountId)); HeadlessAccountSettingsLoader.getOutgoingSettingsUri(accountId));
@ -436,6 +439,7 @@ public class NotificationController {
/** /**
* Cancels the login failed notification for the given account. * Cancels the login failed notification for the given account.
*/ */
@Override
public void cancelLoginFailedNotification(long accountId) { public void cancelLoginFailedNotification(long accountId) {
mNotificationManager.cancel(getLoginFailedNotificationId(accountId)); mNotificationManager.cancel(getLoginFailedNotificationId(accountId));
} }
@ -446,6 +450,7 @@ public class NotificationController {
* *
* NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS) * NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/ */
@Override
public void showPasswordExpiringNotificationSynchronous(long accountId) { public void showPasswordExpiringNotificationSynchronous(long accountId) {
final Account account = Account.restoreAccountWithId(mContext, accountId); final Account account = Account.restoreAccountWithId(mContext, accountId);
if (account == null) return; if (account == null) return;
@ -466,6 +471,7 @@ public class NotificationController {
* *
* NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS) * NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS)
*/ */
@Override
public void showPasswordExpiredNotificationSynchronous(long accountId) { public void showPasswordExpiredNotificationSynchronous(long accountId) {
final Account account = Account.restoreAccountWithId(mContext, accountId); final Account account = Account.restoreAccountWithId(mContext, accountId);
if (account == null) return; if (account == null) return;
@ -482,6 +488,7 @@ public class NotificationController {
/** /**
* Cancels any password expire notifications [both expired & expiring]. * Cancels any password expire notifications [both expired & expiring].
*/ */
@Override
public void cancelPasswordExpirationNotifications() { public void cancelPasswordExpirationNotifications() {
mNotificationManager.cancel(NOTIFICATION_ID_PASSWORD_EXPIRING); mNotificationManager.cancel(NOTIFICATION_ID_PASSWORD_EXPIRING);
mNotificationManager.cancel(NOTIFICATION_ID_PASSWORD_EXPIRED); 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 * Show (or update) a security needed notification. If tapped, the user is taken to a
* dialog asking whether he wants to update his settings. * dialog asking whether he wants to update his settings.
*/ */
@Override
public void showSecurityNeededNotification(Account account) { public void showSecurityNeededNotification(Account account) {
Intent intent = AccountSecurity.actionUpdateSecurityIntent(mContext, account.mId, true); Intent intent = AccountSecurity.actionUpdateSecurityIntent(mContext, account.mId, true);
String accountName = account.getDisplayName(); 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 * 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 * account settings screen where he can view the list of enforced policies
*/ */
@Override
public void showSecurityChangedNotification(Account account) { public void showSecurityChangedNotification(Account account) {
final Intent intent = new Intent(Intent.ACTION_VIEW, final Intent intent = new Intent(Intent.ACTION_VIEW,
HeadlessAccountSettingsLoader.getIncomingSettingsUri(account.getId())); EmailProvider.getIncomingSettingsUri(account.getId()));
final String accountName = account.getDisplayName(); final String accountName = account.getDisplayName();
final String ticker = final String ticker =
mContext.getString(R.string.security_changed_ticker_fmt, accountName); 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 * 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 * account settings screen where he can view the list of unsupported policies
*/ */
@Override
public void showSecurityUnsupportedNotification(Account account) { public void showSecurityUnsupportedNotification(Account account) {
final Intent intent = new Intent(Intent.ACTION_VIEW, final Intent intent = new Intent(Intent.ACTION_VIEW,
HeadlessAccountSettingsLoader.getIncomingSettingsUri(account.getId())); EmailProvider.getIncomingSettingsUri(account.getId()));
final String accountName = account.getDisplayName(); final String accountName = account.getDisplayName();
final String ticker = final String ticker =
mContext.getString(R.string.security_unsupported_ticker_fmt, accountName); mContext.getString(R.string.security_unsupported_ticker_fmt, accountName);
@ -536,6 +546,7 @@ public class NotificationController {
/** /**
* Cancels all security needed notifications. * Cancels all security needed notifications.
*/ */
@Override
public void cancelSecurityNeededNotification() { public void cancelSecurityNeededNotification() {
EmailAsyncTask.runAsyncParallel(new Runnable() { EmailAsyncTask.runAsyncParallel(new Runnable() {
@Override @Override
@ -559,7 +570,8 @@ public class NotificationController {
* Cancels all notifications for the specified account id. This includes new mail notifications, * Cancels all notifications for the specified account id. This includes new mail notifications,
* as well as special login/security 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 final EmailServiceUtils.EmailServiceInfo serviceInfo
= EmailServiceUtils.getServiceInfoForAccount(context, account.mId); = EmailServiceUtils.getServiceInfoForAccount(context, account.mId);
if (serviceInfo == null) { 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 = final Uri accountUri =
intent.getParcelableExtra(UIProvider.UpdateNotificationExtras.EXTRA_ACCOUNT); intent.getParcelableExtra(UIProvider.UpdateNotificationExtras.EXTRA_ACCOUNT);
final Uri folderUri = final Uri folderUri =

View File

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

View File

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

View File

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

View File

@ -43,6 +43,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Toast; import android.widget.Toast;
import com.android.email.R; import com.android.email.R;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.email.service.EmailServiceUtils; import com.android.email.service.EmailServiceUtils;
import com.android.emailcommon.VendorPolicyLoader; import com.android.emailcommon.VendorPolicyLoader;
import com.android.emailcommon.provider.Account; 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. * and the appropriate incoming/outgoing information will be filled in automatically.
*/ */
private static String INTENT_FORCE_CREATE_ACCOUNT; 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_EMAIL = "EMAIL";
private static final String EXTRA_CREATE_ACCOUNT_USER = "USER"; private static final String EXTRA_CREATE_ACCOUNT_USER = "USER";
private static final String EXTRA_CREATE_ACCOUNT_PASSWORD = "PASSWORD"; 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 static final int EXISTING_ACCOUNTS_LOADER_ID = 1;
private Map<String, String> mExistingAccountsMap; 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 @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -250,11 +229,13 @@ public class AccountSetupFinal extends AccountSetupActivity
// Initialize the SetupDataFragment // Initialize the SetupDataFragment
if (INTENT_FORCE_CREATE_ACCOUNT.equals(action)) { if (INTENT_FORCE_CREATE_ACCOUNT.equals(action)) {
mSetupData.setFlowMode(SetupDataFragment.FLOW_MODE_FORCE_CREATE); mSetupData.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE);
} else { } else {
final int intentFlowMode = intent.getIntExtra(EXTRA_FLOW_MODE, final int intentFlowMode = intent.getIntExtra(
SetupDataFragment.FLOW_MODE_UNSPECIFIED); AuthenticatorSetupIntentHelper.EXTRA_FLOW_MODE,
final String flowAccountType = intent.getStringExtra(EXTRA_FLOW_ACCOUNT_TYPE); AuthenticatorSetupIntentHelper.FLOW_MODE_UNSPECIFIED);
final String flowAccountType = intent.getStringExtra(
AuthenticatorSetupIntentHelper.EXTRA_FLOW_ACCOUNT_TYPE);
mSetupData.setAmProtocol( mSetupData.setAmProtocol(
EmailServiceUtils.getProtocolFromAccountType(this, flowAccountType)); EmailServiceUtils.getProtocolFromAccountType(this, flowAccountType));
mSetupData.setFlowMode(intentFlowMode); mSetupData.setFlowMode(intentFlowMode);
@ -273,8 +254,8 @@ public class AccountSetupFinal extends AccountSetupActivity
mPasswordFailed = false; mPasswordFailed = false;
} }
if (!mIsProcessing if (!mIsProcessing && mSetupData.getFlowMode() ==
&& mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) { AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE) {
/** /**
* To support continuous testing, we allow the forced creation of accounts. * 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 * 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: case STATE_CREATING:
mState = STATE_NAMES; mState = STATE_NAMES;
updateContentFragment(true /* addToBackstack */); updateContentFragment(true /* addToBackstack */);
if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) { if (mSetupData.getFlowMode() ==
AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE) {
getFragmentManager().executePendingTransactions(); getFragmentManager().executePendingTransactions();
initiateAccountFinalize(); initiateAccountFinalize();
} }

View File

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

View File

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

View File

@ -21,13 +21,6 @@ import com.android.mail.ui.MailAsyncTaskLoader;
*/ */
public class HeadlessAccountSettingsLoader extends Activity { 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) { public static Uri getOutgoingSettingsUri(long accountId) {
final Uri.Builder baseUri = Uri.parse("auth://" + EmailContent.EMAIL_PACKAGE_NAME + final Uri.Builder baseUri = Uri.parse("auth://" + EmailContent.EMAIL_PACKAGE_NAME +
".ACCOUNT_SETTINGS/outgoing/").buildUpon(); ".ACCOUNT_SETTINGS/outgoing/").buildUpon();

View File

@ -7,6 +7,7 @@ import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import com.android.email.service.EmailServiceUtils; import com.android.email.service.EmailServiceUtils;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.Account; import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth; import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.provider.Policy; 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 // The "extra" name for the Bundle saved with SetupData
public static final String EXTRA_SETUP_DATA = "com.android.email.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 // 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 // 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 // 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_CALLER = 5;
public static final int FLOW_MODE_RETURN_TO_MESSAGE_LIST = 6; 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_RETURN_NO_ACCOUNTS_RESULT = 7;
public static final int FLOW_MODE_NO_ACCOUNTS = 8;
// Mode bits for AccountSetupCheckSettings, indicating the type of check requested // Mode bits for AccountSetupCheckSettings, indicating the type of check requested
public static final int CHECK_INCOMING = 1; 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"; private static final String SAVESTATE_AM_PROTOCOL = "SetupDataFragment.amProtocol";
// All access will be through getters/setters // All access will be through getters/setters
private int mFlowMode = FLOW_MODE_NORMAL; private int mFlowMode = AuthenticatorSetupIntentHelper.FLOW_MODE_NORMAL;
private Account mAccount; private Account mAccount;
private String mEmail; private String mEmail;
private Bundle mCredentialResults; private Bundle mCredentialResults;

View File

@ -26,21 +26,14 @@ import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import com.android.email.NotificationController;
import com.android.email.Preferences; import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.provider.EmailProvider; import com.android.email.provider.EmailProvider;
import com.android.email.service.AttachmentService; import com.android.email.service.AttachmentService;
import com.android.email.service.EmailServiceUtils; import com.android.email.service.EmailServiceUtils;
import com.android.emailcommon.Logging; import com.android.emailcommon.Logging;
import com.android.emailcommon.TempDirectory; 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.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.IntentUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.mail.providers.Folder; import com.android.mail.providers.Folder;
import com.android.mail.providers.UIProvider; import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogTag; 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 @Override
public void onCreate(Bundle bundle) { public void onCreate(Bundle bundle) {
final Intent intent = getIntent(); 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 // Make sure all required services are running when the app is started (can prevent
// issues after an adb sync/install) // 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.R;
import com.android.email.activity.setup.AccountSetupFinal; import com.android.email.activity.setup.AccountSetupFinal;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
public class EmailAccountCacheProvider extends MailAppProvider { public class EmailAccountCacheProvider extends MailAppProvider {
// Content provider for Email // Content provider for Email
@ -36,6 +37,6 @@ public class EmailAccountCacheProvider extends MailAppProvider {
@Override @Override
protected Intent getNoAccountsIntent(Context context) { 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 android.widget.EditText;
import com.android.email.R; import com.android.email.R;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.emailcommon.provider.Account; import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth; import com.android.emailcommon.provider.HostAuth;
@ -198,7 +199,7 @@ public class AccountSetupIncomingTests extends
auth.setHostAuthFromString(storeUriString); auth.setHostAuthFromString(storeUriString);
final SetupDataFragment setupDataFragment = final SetupDataFragment setupDataFragment =
new SetupDataFragment(); new SetupDataFragment();
setupDataFragment.setFlowMode(SetupDataFragment.FLOW_MODE_NORMAL); setupDataFragment.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_NORMAL);
setupDataFragment.setAccount(account); setupDataFragment.setAccount(account);
final Intent i = new Intent(AccountSetupFinal.ACTION_JUMP_TO_INCOMING); final Intent i = new Intent(AccountSetupFinal.ACTION_JUMP_TO_INCOMING);
i.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupDataFragment); i.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupDataFragment);

View File

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

View File

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