summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk6
-rw-r--r--src/com/android/email/Controller.java14
-rw-r--r--src/com/android/email/ExchangeUtils.java12
-rw-r--r--src/com/android/email/activity/MessageViewFragment.java2
-rw-r--r--src/com/android/email/activity/setup/AccountCheckSettingsFragment.java2
-rw-r--r--src/com/android/email/mail/store/ExchangeStore.java4
-rw-r--r--src/com/android/email/mail/store/ImapStore.java2
-rw-r--r--src/com/android/email/mail/store/Pop3Store.java2
-rw-r--r--src/com/android/email/service/AttachmentDownloadService.java7
-rw-r--r--src/com/android/email/service/EmailServiceProxy.java354
-rw-r--r--src/com/android/emailcommon/Api.java24
-rw-r--r--src/com/android/emailcommon/service/EmailServiceConstants.java (renamed from src/com/android/email/service/EmailServiceConstants.java)2
-rw-r--r--src/com/android/emailcommon/service/EmailServiceProxy.java264
-rw-r--r--src/com/android/emailcommon/service/EmailServiceStatus.java (renamed from src/com/android/email/service/EmailServiceStatus.java)2
-rw-r--r--src/com/android/emailcommon/service/IEmailService.aidl (renamed from src/com/android/email/service/IEmailService.aidl)29
-rw-r--r--src/com/android/emailcommon/service/IEmailServiceCallback.aidl (renamed from src/com/android/email/service/IEmailServiceCallback.aidl)2
-rw-r--r--src/com/android/emailcommon/service/ServiceProxy.java196
-rw-r--r--src/com/android/exchange/EasOutboxService.java2
-rw-r--r--src/com/android/exchange/EasSyncService.java6
-rw-r--r--src/com/android/exchange/ExchangeService.java20
-rw-r--r--tests/src/com/android/email/service/AttachmentDownloadServiceTests.java1
21 files changed, 555 insertions, 398 deletions
diff --git a/Android.mk b/Android.mk
index 104fa3e57..960ed4315 100644
--- a/Android.mk
+++ b/Android.mk
@@ -18,11 +18,9 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-# EXCHANGE-REMOVE-SECTION-START
LOCAL_SRC_FILES += \
- src/com/android/email/service/IEmailService.aidl \
- src/com/android/email/service/IEmailServiceCallback.aidl
-# EXCHANGE-REMOVE-SECTION-END
+ src/com/android/emailcommon/service/IEmailService.aidl \
+ src/com/android/emailcommon/service/IEmailServiceCallback.aidl
LOCAL_STATIC_JAVA_LIBRARIES := android-common
# Revive this when the app is unbundled.
diff --git a/src/com/android/email/Controller.java b/src/com/android/email/Controller.java
index 47667b073..b99c48e72 100644
--- a/src/com/android/email/Controller.java
+++ b/src/com/android/email/Controller.java
@@ -17,9 +17,9 @@
package com.android.email;
import com.android.email.mail.AuthenticationFailedException;
-import com.android.email.mail.Folder.MessageRetrievalListener;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Store;
+import com.android.email.mail.Folder.MessageRetrievalListener;
import com.android.email.mail.store.Pop3Store.Pop3Message;
import com.android.email.provider.AttachmentProvider;
import com.android.email.provider.EmailContent;
@@ -30,9 +30,10 @@ import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns;
-import com.android.email.service.EmailServiceStatus;
-import com.android.email.service.IEmailService;
-import com.android.email.service.IEmailServiceCallback;
+import com.android.emailcommon.Api;
+import com.android.emailcommon.service.EmailServiceStatus;
+import com.android.emailcommon.service.IEmailService;
+import com.android.emailcommon.service.IEmailServiceCallback;
import android.app.Service;
import android.content.ContentResolver;
@@ -1686,6 +1687,11 @@ public class Controller {
public void deleteAccountPIMData(long accountId) throws RemoteException {
}
+
+ @Override
+ public int getApiLevel() throws RemoteException {
+ return Api.LEVEL;
+ }
};
@Override
diff --git a/src/com/android/email/ExchangeUtils.java b/src/com/android/email/ExchangeUtils.java
index 0be3debaf..61cef6a30 100644
--- a/src/com/android/email/ExchangeUtils.java
+++ b/src/com/android/email/ExchangeUtils.java
@@ -16,9 +16,10 @@
package com.android.email;
-import com.android.email.service.EmailServiceProxy;
-import com.android.email.service.IEmailService;
-import com.android.email.service.IEmailServiceCallback;
+import com.android.emailcommon.Api;
+import com.android.emailcommon.service.EmailServiceProxy;
+import com.android.emailcommon.service.IEmailService;
+import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.exchange.CalendarSyncEnabler;
import com.android.exchange.ExchangeService;
@@ -143,6 +144,11 @@ public class ExchangeUtils {
}
@Override
+ public int getApiLevel() throws RemoteException {
+ return Api.LEVEL;
+ }
+
+ @Override
public IBinder onBind(Intent intent) {
return null;
}
diff --git a/src/com/android/email/activity/MessageViewFragment.java b/src/com/android/email/activity/MessageViewFragment.java
index f14b77789..1dff7b38a 100644
--- a/src/com/android/email/activity/MessageViewFragment.java
+++ b/src/com/android/email/activity/MessageViewFragment.java
@@ -23,7 +23,7 @@ import com.android.email.mail.MeetingInfo;
import com.android.email.mail.PackedString;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.Message;
-import com.android.email.service.EmailServiceConstants;
+import com.android.emailcommon.service.EmailServiceConstants;
import android.app.Activity;
import android.content.res.Resources;
diff --git a/src/com/android/email/activity/setup/AccountCheckSettingsFragment.java b/src/com/android/email/activity/setup/AccountCheckSettingsFragment.java
index b3984fe75..6f5a47c36 100644
--- a/src/com/android/email/activity/setup/AccountCheckSettingsFragment.java
+++ b/src/com/android/email/activity/setup/AccountCheckSettingsFragment.java
@@ -25,7 +25,7 @@ import com.android.email.mail.Sender;
import com.android.email.mail.Store;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.HostAuth;
-import com.android.email.service.EmailServiceProxy;
+import com.android.emailcommon.service.EmailServiceProxy;
import android.app.Activity;
import android.app.AlertDialog;
diff --git a/src/com/android/email/mail/store/ExchangeStore.java b/src/com/android/email/mail/store/ExchangeStore.java
index 0d06e7693..ace052bba 100644
--- a/src/com/android/email/mail/store/ExchangeStore.java
+++ b/src/com/android/email/mail/store/ExchangeStore.java
@@ -21,8 +21,8 @@ import com.android.email.mail.Folder;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Store;
import com.android.email.mail.StoreSynchronizer;
-import com.android.email.service.EmailServiceProxy;
-import com.android.email.service.IEmailService;
+import com.android.emailcommon.service.EmailServiceProxy;
+import com.android.emailcommon.service.IEmailService;
import android.content.Context;
import android.os.Bundle;
diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java
index 4b43d3711..ebe1d3ec0 100644
--- a/src/com/android/email/mail/store/ImapStore.java
+++ b/src/com/android/email/mail/store/ImapStore.java
@@ -47,7 +47,7 @@ import com.android.email.mail.transport.CountingOutputStream;
import com.android.email.mail.transport.DiscourseLogger;
import com.android.email.mail.transport.EOLConvertingOutputStream;
import com.android.email.mail.transport.MailTransport;
-import com.android.email.service.EmailServiceProxy;
+import com.android.emailcommon.service.EmailServiceProxy;
import com.beetstra.jutf7.CharsetProvider;
import android.content.Context;
diff --git a/src/com/android/email/mail/store/Pop3Store.java b/src/com/android/email/mail/store/Pop3Store.java
index 6f0ccd27e..3bd7145f5 100644
--- a/src/com/android/email/mail/store/Pop3Store.java
+++ b/src/com/android/email/mail/store/Pop3Store.java
@@ -30,7 +30,7 @@ import com.android.email.mail.Folder.OpenMode;
import com.android.email.mail.internet.MimeMessage;
import com.android.email.mail.transport.LoggingInputStream;
import com.android.email.mail.transport.MailTransport;
-import com.android.email.service.EmailServiceProxy;
+import com.android.emailcommon.service.EmailServiceProxy;
import android.content.Context;
import android.os.Bundle;
diff --git a/src/com/android/email/service/AttachmentDownloadService.java b/src/com/android/email/service/AttachmentDownloadService.java
index 4fae126eb..2f155f04f 100644
--- a/src/com/android/email/service/AttachmentDownloadService.java
+++ b/src/com/android/email/service/AttachmentDownloadService.java
@@ -17,17 +17,20 @@
package com.android.email.service;
import com.android.email.AttachmentInfo;
-import com.android.email.Controller.ControllerService;
import com.android.email.Email;
import com.android.email.EmailConnectivityManager;
-import com.android.email.ExchangeUtils.NullEmailService;
import com.android.email.NotificationController;
import com.android.email.Utility;
+import com.android.email.Controller.ControllerService;
+import com.android.email.ExchangeUtils.NullEmailService;
import com.android.email.provider.AttachmentProvider;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Attachment;
import com.android.email.provider.EmailContent.Message;
+import com.android.emailcommon.service.EmailServiceProxy;
+import com.android.emailcommon.service.EmailServiceStatus;
+import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.exchange.ExchangeService;
import android.accounts.AccountManager;
diff --git a/src/com/android/email/service/EmailServiceProxy.java b/src/com/android/email/service/EmailServiceProxy.java
deleted file mode 100644
index 959843201..000000000
--- a/src/com/android/email/service/EmailServiceProxy.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.email.service;
-
-import com.android.email.mail.MessagingException;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.Debug;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * The EmailServiceProxy class provides a simple interface for the UI to call into the various
- * EmailService classes (e.g. ExchangeService for EAS). It wraps the service connect/disconnect
- * process so that the caller need not be concerned with it.
- *
- * Use the class like this:
- * new EmailServiceClass(context, class).loadAttachment(attachmentId, callback)
- *
- * Methods without a return value return immediately (i.e. are asynchronous); methods with a
- * return value wait for a result from the Service (i.e. they should not be called from the UI
- * thread) with a default timeout of 30 seconds (settable)
- *
- * An EmailServiceProxy object cannot be reused (trying to do so generates a RemoteException)
- */
-
-public class EmailServiceProxy implements IEmailService {
- private static final boolean DEBUG_PROXY = false; // DO NOT CHECK THIS IN SET TO TRUE
- private static final String TAG = "EmailServiceProxy";
-
- public static final String AUTO_DISCOVER_BUNDLE_ERROR_CODE = "autodiscover_error_code";
- public static final String AUTO_DISCOVER_BUNDLE_HOST_AUTH = "autodiscover_host_auth";
-
- public static final String VALIDATE_BUNDLE_RESULT_CODE = "validate_result_code";
- public static final String VALIDATE_BUNDLE_POLICY_SET = "validate_policy_set";
- public static final String VALIDATE_BUNDLE_ERROR_MESSAGE = "validate_error_message";
-
- private final Context mContext;
- private final Class<?> mClass;
- private final IEmailServiceCallback mCallback;
- private Runnable mRunnable;
- private final ServiceConnection mExchangeServiceConnection = new EmailServiceConnection ();
- private IEmailService mService = null;
- private Object mReturn = null;
- // Service call timeout (in seconds)
- private int mTimeout = 45;
- private boolean mDead = false;
-
- public EmailServiceProxy(Context _context, Class<?> _class) {
- this(_context, _class, null);
- }
-
- public EmailServiceProxy(Context _context, Class<?> _class, IEmailServiceCallback _callback) {
- mContext = _context;
- mClass = _class;
- mCallback = _callback;
- // Proxy calls have a timeout, and this can cause failures while debugging due to the
- // far slower execution speed. In particular, validate calls fail regularly with ssl
- // connections at the default timeout (30 seconds)
- if (Debug.isDebuggerConnected()) {
- mTimeout <<= 2;
- }
- }
-
- class EmailServiceConnection implements ServiceConnection {
- public void onServiceConnected(ComponentName name, IBinder binder) {
- mService = IEmailService.Stub.asInterface(binder);
- if (DEBUG_PROXY) {
- Log.v(TAG, "Service " + mClass.getSimpleName() + " connected");
- }
- // Run our task on a new thread
- new Thread(new Runnable() {
- public void run() {
- runTask();
- }}).start();
- }
-
- public void onServiceDisconnected(ComponentName name) {
- if (DEBUG_PROXY) {
- Log.v(TAG, "Service " + mClass.getSimpleName() + " disconnected");
- }
- }
- }
-
- public EmailServiceProxy setTimeout(int secs) {
- mTimeout = secs;
- return this;
- }
-
- private void runTask() {
- Thread thread = new Thread(mRunnable);
- thread.start();
- try {
- thread.join();
- } catch (InterruptedException e) {
- }
-
- try {
- mContext.unbindService(mExchangeServiceConnection);
- } catch (IllegalArgumentException e) {
- // This can happen if the user ended the activity that was using the service
- // This is harmless, but we've got to catch it
- }
-
- mDead = true;
- synchronized(mExchangeServiceConnection) {
- if (DEBUG_PROXY) {
- Log.v(TAG, "Service task completed; disconnecting");
- }
- mExchangeServiceConnection.notify();
- }
- }
-
- private void setTask(Runnable runnable) throws RemoteException {
- if (mDead) {
- throw new RemoteException();
- }
- mRunnable = runnable;
- if (DEBUG_PROXY) {
- Log.v(TAG, "Service " + mClass.getSimpleName() + " bind requested");
- }
- mContext.bindService(new Intent(mContext, mClass), mExchangeServiceConnection,
- Context.BIND_AUTO_CREATE);
- }
-
- public void waitForCompletion() {
- synchronized (mExchangeServiceConnection) {
- long time = System.currentTimeMillis();
- try {
- if (DEBUG_PROXY) {
- Log.v(TAG, "Waiting for task to complete...");
- }
- mExchangeServiceConnection.wait(mTimeout * 1000L);
- } catch (InterruptedException e) {
- // Can be ignored safely
- }
- if (DEBUG_PROXY) {
- Log.v(TAG, "Wait finished in " + (System.currentTimeMillis() - time) + "ms");
- }
- }
- }
-
- public void loadAttachment(final long attachmentId, final String destinationFile,
- final String contentUriString, final boolean background) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- if (mCallback != null) mService.setCallback(mCallback);
- mService.loadAttachment(
- attachmentId, destinationFile, contentUriString, background);
- } catch (RemoteException e) {
- try {
- // Try to send a callback (if set)
- if (mCallback != null) {
- mCallback.loadAttachmentStatus(-1, attachmentId,
- EmailServiceStatus.REMOTE_EXCEPTION, 0);
- }
- } catch (RemoteException e1) {
- }
- }
- }
- });
- }
-
- public void startSync(final long mailboxId, final boolean userRequest) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- if (mCallback != null) mService.setCallback(mCallback);
- mService.startSync(mailboxId, userRequest);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public void stopSync(final long mailboxId) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- if (mCallback != null) mService.setCallback(mCallback);
- mService.stopSync(mailboxId);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public Bundle validate(final String protocol, final String host, final String userName,
- final String password, final int port, final boolean ssl,
- final boolean trustCertificates) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- if (mCallback != null) mService.setCallback(mCallback);
- mReturn = mService.validate(protocol, host, userName, password, port, ssl,
- trustCertificates);
- } catch (RemoteException e) {
- }
- }
- });
- waitForCompletion();
- if (mReturn == null) {
- Bundle bundle = new Bundle();
- bundle.putInt(VALIDATE_BUNDLE_RESULT_CODE, MessagingException.UNSPECIFIED_EXCEPTION);
- return bundle;
- } else {
- Bundle bundle = (Bundle) mReturn;
- Log.v(TAG, "validate returns " + bundle.getInt(VALIDATE_BUNDLE_RESULT_CODE));
- return bundle;
- }
- }
-
- public Bundle autoDiscover(final String userName, final String password)
- throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- if (mCallback != null) mService.setCallback(mCallback);
- mReturn = mService.autoDiscover(userName, password);
- } catch (RemoteException e) {
- }
- }
- });
- waitForCompletion();
- if (mReturn == null) {
- return null;
- } else {
- Bundle bundle = (Bundle) mReturn;
- Log.v(TAG, "autoDiscover returns " + bundle.getInt(AUTO_DISCOVER_BUNDLE_ERROR_CODE));
- return bundle;
- }
- }
-
- public void updateFolderList(final long accountId) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- if (mCallback != null) mService.setCallback(mCallback);
- mService.updateFolderList(accountId);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public void setLogging(final int on) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- if (mCallback != null) mService.setCallback(mCallback);
- mService.setLogging(on);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public void setCallback(final IEmailServiceCallback cb) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- mService.setCallback(cb);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public void hostChanged(final long accountId) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- mService.hostChanged(accountId);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public void sendMeetingResponse(final long messageId, final int response) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- if (mCallback != null) mService.setCallback(mCallback);
- mService.sendMeetingResponse(messageId, response);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public void loadMore(long messageId) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- public boolean createFolder(long accountId, String name) throws RemoteException {
- return false;
- }
-
- public boolean deleteFolder(long accountId, String name) throws RemoteException {
- return false;
- }
-
- public boolean renameFolder(long accountId, String oldName, String newName)
- throws RemoteException {
- return false;
- }
-
- public void moveMessage(final long messageId, final long mailboxId) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- mService.moveMessage(messageId, mailboxId);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public void deleteAccountPIMData(final long accountId) throws RemoteException {
- setTask(new Runnable () {
- public void run() {
- try {
- mService.deleteAccountPIMData(accountId);
- } catch (RemoteException e) {
- }
- }
- });
- }
-
- public IBinder asBinder() {
- return null;
- }
-}
diff --git a/src/com/android/emailcommon/Api.java b/src/com/android/emailcommon/Api.java
new file mode 100644
index 000000000..ed284d7fb
--- /dev/null
+++ b/src/com/android/emailcommon/Api.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2011 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.emailcommon;
+
+/**
+ * This class will be used for API-related definitions; for now, just the api "level"
+ */
+public class Api {
+ public static final int LEVEL = 1;
+}
diff --git a/src/com/android/email/service/EmailServiceConstants.java b/src/com/android/emailcommon/service/EmailServiceConstants.java
index 8a5238f28..b229ffc64 100644
--- a/src/com/android/email/service/EmailServiceConstants.java
+++ b/src/com/android/emailcommon/service/EmailServiceConstants.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.email.service;
+package com.android.emailcommon.service;
public class EmailServiceConstants {
public static final int MEETING_REQUEST_ACCEPTED = 1;
diff --git a/src/com/android/emailcommon/service/EmailServiceProxy.java b/src/com/android/emailcommon/service/EmailServiceProxy.java
new file mode 100644
index 000000000..af2ceff81
--- /dev/null
+++ b/src/com/android/emailcommon/service/EmailServiceProxy.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2009 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.emailcommon.service;
+
+import com.android.email.mail.MessagingException;
+import com.android.email.provider.EmailContent.HostAuth;
+import com.android.emailcommon.Api;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * The EmailServiceProxy class provides a simple interface for the UI to call into the various
+ * EmailService classes (e.g. ExchangeService for EAS). It wraps the service connect/disconnect
+ * process so that the caller need not be concerned with it.
+ *
+ * Use the class like this:
+ * new EmailServiceClass(context, class).loadAttachment(attachmentId, callback)
+ *
+ * Methods without a return value return immediately (i.e. are asynchronous); methods with a
+ * return value wait for a result from the Service (i.e. they should not be called from the UI
+ * thread) with a default timeout of 30 seconds (settable)
+ *
+ * An EmailServiceProxy object cannot be reused (trying to do so generates a RemoteException)
+ */
+
+public class EmailServiceProxy extends ServiceProxy implements IEmailService {
+ private static final String TAG = "EmailServiceProxy";
+
+ // Private intent that will be used to connect to an independent Exchange service
+ public static final String EXCHANGE_INTENT = "com.android.email.EXCHANGE_INTENT";
+
+ public static final String AUTO_DISCOVER_BUNDLE_ERROR_CODE = "autodiscover_error_code";
+ public static final String AUTO_DISCOVER_BUNDLE_HOST_AUTH = "autodiscover_host_auth";
+
+ public static final String VALIDATE_BUNDLE_RESULT_CODE = "validate_result_code";
+ public static final String VALIDATE_BUNDLE_POLICY_SET = "validate_policy_set";
+ public static final String VALIDATE_BUNDLE_ERROR_MESSAGE = "validate_error_message";
+
+ private final IEmailServiceCallback mCallback;
+ private Object mReturn = null;
+ private IEmailService mService;
+
+ // Standard debugging
+ public static final int DEBUG_BIT = 1;
+ // Verbose (parser) logging
+ public static final int DEBUG_VERBOSE_BIT = 2;
+ // File (SD card) logging
+ public static final int DEBUG_FILE_BIT = 4;
+
+ // The first two constructors are used with local services that can be referenced by class
+ public EmailServiceProxy(Context _context, Class<?> _class) {
+ this(_context, _class, null);
+ }
+
+ public EmailServiceProxy(Context _context, Class<?> _class, IEmailServiceCallback _callback) {
+ super(_context, new Intent(_context, _class));
+ mCallback = _callback;
+ }
+
+ // The following two constructors are used with remote services that must be referenced by
+ // a known action or by a prebuilt intent
+ public EmailServiceProxy(Context _context, Intent _intent, IEmailServiceCallback _callback) {
+ super(_context, _intent);
+ mCallback = _callback;
+ }
+
+ public EmailServiceProxy(Context _context, String _action, IEmailServiceCallback _callback) {
+ super(_context, new Intent(_action));
+ mCallback = _callback;
+ }
+
+ @Override
+ public void onConnected(IBinder binder) {
+ mService = IEmailService.Stub.asInterface(binder);
+ }
+
+ @Override
+ public int getApiLevel() {
+ return Api.LEVEL;
+ }
+
+ public void loadAttachment(final long attachmentId, final String destinationFile,
+ final String contentUriString, final boolean background) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ try {
+ if (mCallback != null) mService.setCallback(mCallback);
+ mService.loadAttachment(
+ attachmentId, destinationFile, contentUriString, background);
+ } catch (RemoteException e) {
+ try {
+ // Try to send a callback (if set)
+ if (mCallback != null) {
+ mCallback.loadAttachmentStatus(-1, attachmentId,
+ EmailServiceStatus.REMOTE_EXCEPTION, 0);
+ }
+ } catch (RemoteException e1) {
+ }
+ }
+ }
+ }, "loadAttachment");
+ }
+
+ public void startSync(final long mailboxId, final boolean userRequest) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ if (mCallback != null) mService.setCallback(mCallback);
+ mService.startSync(mailboxId, userRequest);
+ }
+ }, "startSync");
+ }
+
+ public void stopSync(final long mailboxId) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ if (mCallback != null) mService.setCallback(mCallback);
+ mService.stopSync(mailboxId);
+ }
+ }, "stopSync");
+ }
+
+ public Bundle validate(final String protocol, final String host, final String userName,
+ final String password, final int port, final boolean ssl,
+ final boolean trustCertificates) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException{
+ if (mCallback != null) mService.setCallback(mCallback);
+ mReturn = mService.validate(protocol, host, userName, password, port, ssl,
+ trustCertificates);
+ }
+ }, "validate");
+ waitForCompletion();
+ if (mReturn == null) {
+ Bundle bundle = new Bundle();
+ bundle.putInt(VALIDATE_BUNDLE_RESULT_CODE, MessagingException.UNSPECIFIED_EXCEPTION);
+ return bundle;
+ } else {
+ Bundle bundle = (Bundle) mReturn;
+ // STOPSHIP The following line will be necessary when Email and Exchange are split
+ //bundle.setClassLoader(PolicySet.class.getClassLoader());
+ Log.v(TAG, "validate returns " + bundle.getInt(VALIDATE_BUNDLE_RESULT_CODE));
+ return bundle;
+ }
+ }
+
+ public Bundle autoDiscover(final String userName, final String password)
+ throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException{
+ if (mCallback != null) mService.setCallback(mCallback);
+ mReturn = mService.autoDiscover(userName, password);
+ }
+ }, "autoDiscover");
+ waitForCompletion();
+ if (mReturn == null) {
+ return null;
+ } else {
+ Bundle bundle = (Bundle) mReturn;
+ bundle.setClassLoader(HostAuth.class.getClassLoader());
+ Log.v(TAG, "autoDiscover returns " + bundle.getInt(AUTO_DISCOVER_BUNDLE_ERROR_CODE));
+ return bundle;
+ }
+ }
+
+ public void updateFolderList(final long accountId) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ if (mCallback != null) mService.setCallback(mCallback);
+ mService.updateFolderList(accountId);
+ }
+ }, "updateFolderList");
+ }
+
+ public void setLogging(final int on) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ if (mCallback != null) mService.setCallback(mCallback);
+ mService.setLogging(on);
+ }
+ }, "setLogging");
+ }
+
+ public void setCallback(final IEmailServiceCallback cb) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ mService.setCallback(cb);
+ }
+ }, "setCallback");
+ }
+
+ public void hostChanged(final long accountId) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ mService.hostChanged(accountId);
+ }
+ }, "hostChanged");
+ }
+
+ public void sendMeetingResponse(final long messageId, final int response)
+ throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ if (mCallback != null) mService.setCallback(mCallback);
+ mService.sendMeetingResponse(messageId, response);
+ }
+ }, "sendMeetingResponse");
+ }
+
+ public void loadMore(long messageId) throws RemoteException {
+ // TODO Auto-generated method stub
+ }
+
+ public boolean createFolder(long accountId, String name) throws RemoteException {
+ return false;
+ }
+
+ public boolean deleteFolder(long accountId, String name) throws RemoteException {
+ return false;
+ }
+
+ public boolean renameFolder(long accountId, String oldName, String newName)
+ throws RemoteException {
+ return false;
+ }
+
+ public void moveMessage(final long messageId, final long mailboxId) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ mService.moveMessage(messageId, mailboxId);
+ }
+ }, "moveMessage");
+ }
+
+ public void deleteAccountPIMData(final long accountId) throws RemoteException {
+ setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ mService.deleteAccountPIMData(accountId);
+ }
+ }, "deleteAccountPIMData");
+ }
+
+ public IBinder asBinder() {
+ return null;
+ }
+}
diff --git a/src/com/android/email/service/EmailServiceStatus.java b/src/com/android/emailcommon/service/EmailServiceStatus.java
index 135797637..055f79a33 100644
--- a/src/com/android/email/service/EmailServiceStatus.java
+++ b/src/com/android/emailcommon/service/EmailServiceStatus.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.android.email.service;
+package com.android.emailcommon.service;
/**
* Definitions of service status codes returned to IEmailServiceCallback's status method
diff --git a/src/com/android/email/service/IEmailService.aidl b/src/com/android/emailcommon/service/IEmailService.aidl
index 187320895..c91706ace 100644
--- a/src/com/android/email/service/IEmailService.aidl
+++ b/src/com/android/emailcommon/service/IEmailService.aidl
@@ -14,39 +14,46 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.email.service;
-import com.android.email.service.IEmailServiceCallback;
+package com.android.emailcommon.service;
+
+import com.android.emailcommon.service.IEmailServiceCallback;
import android.os.Bundle;
interface IEmailService {
Bundle validate(in String protocol, in String host, in String userName, in String password,
int port, boolean ssl, boolean trustCertificates) ;
- void startSync(long mailboxId, boolean userRequest);
- void stopSync(long mailboxId);
+ oneway void startSync(long mailboxId, boolean userRequest);
+ oneway void stopSync(long mailboxId);
- void loadMore(long messageId);
- void loadAttachment(long attachmentId, String destinationFile, String contentUriString,
+ oneway void loadMore(long messageId);
+ oneway void loadAttachment(long attachmentId, String destinationFile, String contentUriString,
boolean background);
- void updateFolderList(long accountId);
+ oneway void updateFolderList(long accountId);
boolean createFolder(long accountId, String name);
boolean deleteFolder(long accountId, String name);
boolean renameFolder(long accountId, String oldName, String newName);
+ // Must not be oneway; unless an exception is thrown, the caller is guaranteed that the callback
+ // has been registered
void setCallback(IEmailServiceCallback cb);
- void setLogging(int on);
+ oneway void setLogging(int on);
- void hostChanged(long accountId);
+ oneway void hostChanged(long accountId);
Bundle autoDiscover(String userName, String password);
- void sendMeetingResponse(long messageId, int response);
+ oneway void sendMeetingResponse(long messageId, int response);
- void moveMessage(long messageId, long mailboxId);
+ oneway void moveMessage(long messageId, long mailboxId);
+ // Must not be oneway; unless an exception is thrown, the caller is guaranteed that the action
+ // has been completed
void deleteAccountPIMData(long accountId);
+
+ int getApiLevel();
} \ No newline at end of file
diff --git a/src/com/android/email/service/IEmailServiceCallback.aidl b/src/com/android/emailcommon/service/IEmailServiceCallback.aidl
index ac2cb419e..e4c6093fc 100644
--- a/src/com/android/email/service/IEmailServiceCallback.aidl
+++ b/src/com/android/emailcommon/service/IEmailServiceCallback.aidl
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.android.email.service;
+package com.android.emailcommon.service;
oneway interface IEmailServiceCallback {
/*
diff --git a/src/com/android/emailcommon/service/ServiceProxy.java b/src/com/android/emailcommon/service/ServiceProxy.java
new file mode 100644
index 000000000..215fb726f
--- /dev/null
+++ b/src/com/android/emailcommon/service/ServiceProxy.java
@@ -0,0 +1,196 @@
+/*
+ /*
+ * Copyright (C) 2011 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.emailcommon.service;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Debug;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * The EmailServiceProxy class provides a simple interface for the UI to call into the various
+ * EmailService classes (e.g. ExchangeService for EAS). It wraps the service connect/disconnect
+ * process so that the caller need not be concerned with it.
+ *
+ * Use the class like this:
+ * new EmailServiceClass(context, class).loadAttachment(attachmentId, callback)
+ *
+ * Methods without a return value return immediately (i.e. are asynchronous); methods with a
+ * return value wait for a result from the Service (i.e. they should not be called from the UI
+ * thread) with a default timeout of 30 seconds (settable)
+ *
+ * An EmailServiceProxy object cannot be reused (trying to do so generates a RemoteException)
+ */
+
+public abstract class ServiceProxy {
+ private static final boolean DEBUG_PROXY = true; // STOPSHIP DO NOT CHECK THIS IN SET TO TRUE
+ private static final String TAG = "ServiceProxy";
+
+ private final Context mContext;
+ protected final Intent mIntent;
+ private Runnable mRunnable = new ProxyRunnable();
+ private ProxyTask mTask;
+ private String mName = " unnamed";
+ private final ServiceConnection mConnection = new ProxyConnection();
+ // Service call timeout (in seconds)
+ private int mTimeout = 45;
+ private boolean mDead = false;
+
+ public abstract void onConnected(IBinder binder);
+
+ public ServiceProxy(Context _context, Intent _intent) {
+ mContext = _context;
+ mIntent = _intent;
+ if (Debug.isDebuggerConnected()) {
+ mTimeout <<= 2;
+ }
+ }
+
+ private class ProxyConnection implements ServiceConnection {
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ onConnected(binder);
+ if (DEBUG_PROXY) {
+ Log.v(TAG, "Connected: " + name.getShortClassName());
+ }
+ // Run our task on a new thread
+ new Thread(new Runnable() {
+ public void run() {
+ runTask();
+ }}).start();
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG_PROXY) {
+ Log.v(TAG, "Disconnected: " + name.getShortClassName());
+ }
+ }
+ }
+
+ public interface ProxyTask {
+ public void run() throws RemoteException;
+ }
+
+ private class ProxyRunnable implements Runnable {
+ @Override
+ public void run() {
+ try {
+ mTask.run();
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ public ServiceProxy setTimeout(int secs) {
+ mTimeout = secs;
+ return this;
+ }
+
+ public int getTimeout() {
+ return mTimeout;
+ }
+
+ public void endTask() {
+ try {
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException e) {
+ // This can happen if the user ended the activity that was using the service
+ // This is harmless, but we've got to catch it
+ }
+
+ mDead = true;
+ synchronized(mConnection) {
+ if (DEBUG_PROXY) {
+ Log.v(TAG, "Task " + mName + " completed; disconnecting");
+ }
+ mConnection.notify();
+ }
+ }
+
+ private void runTask() {
+ Thread thread = new Thread(mRunnable);
+ thread.start();
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ }
+ endTask();
+ }
+
+ public boolean setTask(ProxyTask task, String name) {
+ mName = name;
+ return setTask(task);
+ }
+
+ public boolean setTask(ProxyTask task) throws IllegalStateException {
+ if (mDead) {
+ throw new IllegalStateException();
+ }
+ mTask = task;
+ if (DEBUG_PROXY) {
+ Log.v(TAG, "Bind requested for task " + mName);
+ }
+ return mContext.bindService(mIntent, mConnection, Context.BIND_AUTO_CREATE);
+ }
+
+ public void waitForCompletion() {
+ synchronized (mConnection) {
+ long time = System.currentTimeMillis();
+ try {
+ if (DEBUG_PROXY) {
+ Log.v(TAG, "Waiting for task " + mName + " to complete...");
+ }
+ mConnection.wait(mTimeout * 1000L);
+ } catch (InterruptedException e) {
+ // Can be ignored safely
+ }
+ if (DEBUG_PROXY) {
+ Log.v(TAG, "Wait finished in " + (System.currentTimeMillis() - time) + "ms");
+ }
+ }
+ }
+
+ public void close() throws RemoteException {
+ if (mDead) {
+ throw new RemoteException();
+ }
+ endTask();
+ }
+
+ /**
+ * Connection test; return indicates whether the remote service can be connected to
+ * @return the result of trying to connect to the remote service
+ */
+ public boolean test() {
+ try {
+ return setTask(new ProxyTask() {
+ public void run() throws RemoteException {
+ if (DEBUG_PROXY) {
+ Log.v(TAG, "Connection test succeeded");
+ }
+ }
+ }, "test");
+ } catch (Exception e) {
+ // For any failure, return false.
+ return false;
+ }
+ }
+}
diff --git a/src/com/android/exchange/EasOutboxService.java b/src/com/android/exchange/EasOutboxService.java
index a4b043cbb..d0392b492 100644
--- a/src/com/android/exchange/EasOutboxService.java
+++ b/src/com/android/exchange/EasOutboxService.java
@@ -28,7 +28,7 @@ import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns;
import com.android.email.provider.EmailContent.SyncColumns;
-import com.android.email.service.EmailServiceStatus;
+import com.android.emailcommon.service.EmailServiceStatus;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
diff --git a/src/com/android/exchange/EasSyncService.java b/src/com/android/exchange/EasSyncService.java
index 98a34d8f2..32441b094 100644
--- a/src/com/android/exchange/EasSyncService.java
+++ b/src/com/android/exchange/EasSyncService.java
@@ -34,9 +34,9 @@ import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns;
import com.android.email.provider.EmailContent.SyncColumns;
-import com.android.email.service.EmailServiceConstants;
-import com.android.email.service.EmailServiceProxy;
-import com.android.email.service.EmailServiceStatus;
+import com.android.emailcommon.service.EmailServiceConstants;
+import com.android.emailcommon.service.EmailServiceProxy;
+import com.android.emailcommon.service.EmailServiceStatus;
import com.android.exchange.adapter.AbstractSyncAdapter;
import com.android.exchange.adapter.AccountSyncAdapter;
import com.android.exchange.adapter.CalendarSyncAdapter;
diff --git a/src/com/android/exchange/ExchangeService.java b/src/com/android/exchange/ExchangeService.java
index 0f0df3693..19bc2264a 100644
--- a/src/com/android/exchange/ExchangeService.java
+++ b/src/com/android/exchange/ExchangeService.java
@@ -23,6 +23,7 @@ import com.android.email.NotificationController;
import com.android.email.Utility;
import com.android.email.mail.transport.SSLUtils;
import com.android.email.provider.EmailContent;
+import com.android.email.provider.EmailProvider;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Attachment;
import com.android.email.provider.EmailContent.HostAuth;
@@ -31,11 +32,11 @@ import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.SyncColumns;
-import com.android.email.provider.EmailProvider;
-import com.android.email.service.EmailServiceStatus;
-import com.android.email.service.IEmailService;
-import com.android.email.service.IEmailServiceCallback;
import com.android.email.service.MailService;
+import com.android.emailcommon.Api;
+import com.android.emailcommon.service.EmailServiceStatus;
+import com.android.emailcommon.service.IEmailService;
+import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.exchange.adapter.CalendarSyncAdapter;
import com.android.exchange.adapter.ContactsSyncAdapter;
import com.android.exchange.utility.FileLogger;
@@ -67,21 +68,21 @@ import android.database.ContentObserver;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
-import android.net.NetworkInfo.State;
import android.net.Uri;
+import android.net.NetworkInfo.State;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.PowerManager.WakeLock;
import android.provider.Calendar;
+import android.provider.ContactsContract;
import android.provider.Calendar.Calendars;
import android.provider.Calendar.Events;
-import android.provider.ContactsContract;
import android.util.Log;
import java.io.BufferedReader;
@@ -462,6 +463,11 @@ public class ExchangeService extends Service implements Runnable {
// Delete the data
ExchangeService.deleteAccountPIMData(accountId);
}
+
+ @Override
+ public int getApiLevel() throws RemoteException {
+ return Api.LEVEL;
+ }
};
private static AccountList collectEasAccounts(Context context, AccountList accounts) {
diff --git a/tests/src/com/android/email/service/AttachmentDownloadServiceTests.java b/tests/src/com/android/email/service/AttachmentDownloadServiceTests.java
index 004bf4e57..8bf9f882a 100644
--- a/tests/src/com/android/email/service/AttachmentDownloadServiceTests.java
+++ b/tests/src/com/android/email/service/AttachmentDownloadServiceTests.java
@@ -26,6 +26,7 @@ import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.ProviderTestUtils;
import com.android.email.service.AttachmentDownloadService.DownloadRequest;
import com.android.email.service.AttachmentDownloadService.DownloadSet;
+import com.android.emailcommon.service.EmailServiceStatus;
import android.content.Context;