Email split, part one: EmailService

* Create emailcommon package
* Move EmailService classes to emailcommon package
* Change references to aidl's to emailcommon package
* Add getApiLevel() command to EmailService

Bug: 3442973

Change-Id: Ic7d2115363cdff6ebb86c46650b0a5b2109b1c72
This commit is contained in:
Marc Blank 2011-02-08 17:50:30 -08:00
parent 34e487594d
commit 0d4fc55861
21 changed files with 555 additions and 398 deletions

View File

@ -18,11 +18,9 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_SRC_FILES := $(call all-java-files-under, src)
# EXCHANGE-REMOVE-SECTION-START
LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += \
src/com/android/email/service/IEmailService.aidl \ src/com/android/emailcommon/service/IEmailService.aidl \
src/com/android/email/service/IEmailServiceCallback.aidl src/com/android/emailcommon/service/IEmailServiceCallback.aidl
# EXCHANGE-REMOVE-SECTION-END
LOCAL_STATIC_JAVA_LIBRARIES := android-common LOCAL_STATIC_JAVA_LIBRARIES := android-common
# Revive this when the app is unbundled. # Revive this when the app is unbundled.

View File

@ -17,9 +17,9 @@
package com.android.email; package com.android.email;
import com.android.email.mail.AuthenticationFailedException; import com.android.email.mail.AuthenticationFailedException;
import com.android.email.mail.Folder.MessageRetrievalListener;
import com.android.email.mail.MessagingException; import com.android.email.mail.MessagingException;
import com.android.email.mail.Store; 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.mail.store.Pop3Store.Pop3Message;
import com.android.email.provider.AttachmentProvider; import com.android.email.provider.AttachmentProvider;
import com.android.email.provider.EmailContent; 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.MailboxColumns;
import com.android.email.provider.EmailContent.Message; import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns; import com.android.email.provider.EmailContent.MessageColumns;
import com.android.email.service.EmailServiceStatus; import com.android.emailcommon.Api;
import com.android.email.service.IEmailService; import com.android.emailcommon.service.EmailServiceStatus;
import com.android.email.service.IEmailServiceCallback; import com.android.emailcommon.service.IEmailService;
import com.android.emailcommon.service.IEmailServiceCallback;
import android.app.Service; import android.app.Service;
import android.content.ContentResolver; import android.content.ContentResolver;
@ -1686,6 +1687,11 @@ public class Controller {
public void deleteAccountPIMData(long accountId) throws RemoteException { public void deleteAccountPIMData(long accountId) throws RemoteException {
} }
@Override
public int getApiLevel() throws RemoteException {
return Api.LEVEL;
}
}; };
@Override @Override

View File

@ -16,9 +16,10 @@
package com.android.email; package com.android.email;
import com.android.email.service.EmailServiceProxy; import com.android.emailcommon.Api;
import com.android.email.service.IEmailService; import com.android.emailcommon.service.EmailServiceProxy;
import com.android.email.service.IEmailServiceCallback; import com.android.emailcommon.service.IEmailService;
import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.exchange.CalendarSyncEnabler; import com.android.exchange.CalendarSyncEnabler;
import com.android.exchange.ExchangeService; import com.android.exchange.ExchangeService;
@ -142,6 +143,11 @@ public class ExchangeUtils {
return null; return null;
} }
@Override
public int getApiLevel() throws RemoteException {
return Api.LEVEL;
}
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return null; return null;

View File

@ -23,7 +23,7 @@ import com.android.email.mail.MeetingInfo;
import com.android.email.mail.PackedString; import com.android.email.mail.PackedString;
import com.android.email.provider.EmailContent.Mailbox; import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.Message; 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.app.Activity;
import android.content.res.Resources; import android.content.res.Resources;

View File

@ -25,7 +25,7 @@ import com.android.email.mail.Sender;
import com.android.email.mail.Store; import com.android.email.mail.Store;
import com.android.email.provider.EmailContent.Account; import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.HostAuth; 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.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;

View File

@ -21,8 +21,8 @@ import com.android.email.mail.Folder;
import com.android.email.mail.MessagingException; import com.android.email.mail.MessagingException;
import com.android.email.mail.Store; import com.android.email.mail.Store;
import com.android.email.mail.StoreSynchronizer; import com.android.email.mail.StoreSynchronizer;
import com.android.email.service.EmailServiceProxy; import com.android.emailcommon.service.EmailServiceProxy;
import com.android.email.service.IEmailService; import com.android.emailcommon.service.IEmailService;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;

View File

@ -47,7 +47,7 @@ import com.android.email.mail.transport.CountingOutputStream;
import com.android.email.mail.transport.DiscourseLogger; import com.android.email.mail.transport.DiscourseLogger;
import com.android.email.mail.transport.EOLConvertingOutputStream; import com.android.email.mail.transport.EOLConvertingOutputStream;
import com.android.email.mail.transport.MailTransport; 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 com.beetstra.jutf7.CharsetProvider;
import android.content.Context; import android.content.Context;

View File

@ -30,7 +30,7 @@ import com.android.email.mail.Folder.OpenMode;
import com.android.email.mail.internet.MimeMessage; import com.android.email.mail.internet.MimeMessage;
import com.android.email.mail.transport.LoggingInputStream; import com.android.email.mail.transport.LoggingInputStream;
import com.android.email.mail.transport.MailTransport; 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.content.Context;
import android.os.Bundle; import android.os.Bundle;

View File

@ -17,17 +17,20 @@
package com.android.email.service; package com.android.email.service;
import com.android.email.AttachmentInfo; import com.android.email.AttachmentInfo;
import com.android.email.Controller.ControllerService;
import com.android.email.Email; import com.android.email.Email;
import com.android.email.EmailConnectivityManager; import com.android.email.EmailConnectivityManager;
import com.android.email.ExchangeUtils.NullEmailService;
import com.android.email.NotificationController; import com.android.email.NotificationController;
import com.android.email.Utility; 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.AttachmentProvider;
import com.android.email.provider.EmailContent; import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account; import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Attachment; import com.android.email.provider.EmailContent.Attachment;
import com.android.email.provider.EmailContent.Message; 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 com.android.exchange.ExchangeService;
import android.accounts.AccountManager; import android.accounts.AccountManager;

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.email.service; package com.android.emailcommon.service;
public class EmailServiceConstants { public class EmailServiceConstants {
public static final int MEETING_REQUEST_ACCEPTED = 1; public static final int MEETING_REQUEST_ACCEPTED = 1;

View File

@ -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;
}
}

View File

@ -15,7 +15,7 @@
* limitations under the License. * 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 * Definitions of service status codes returned to IEmailServiceCallback's status method

View File

@ -14,39 +14,46 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * 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; import android.os.Bundle;
interface IEmailService { interface IEmailService {
Bundle validate(in String protocol, in String host, in String userName, in String password, Bundle validate(in String protocol, in String host, in String userName, in String password,
int port, boolean ssl, boolean trustCertificates) ; int port, boolean ssl, boolean trustCertificates) ;
void startSync(long mailboxId, boolean userRequest); oneway void startSync(long mailboxId, boolean userRequest);
void stopSync(long mailboxId); oneway void stopSync(long mailboxId);
void loadMore(long messageId); oneway void loadMore(long messageId);
void loadAttachment(long attachmentId, String destinationFile, String contentUriString, oneway void loadAttachment(long attachmentId, String destinationFile, String contentUriString,
boolean background); boolean background);
void updateFolderList(long accountId); oneway void updateFolderList(long accountId);
boolean createFolder(long accountId, String name); boolean createFolder(long accountId, String name);
boolean deleteFolder(long accountId, String name); boolean deleteFolder(long accountId, String name);
boolean renameFolder(long accountId, String oldName, String newName); 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 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); 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); void deleteAccountPIMData(long accountId);
int getApiLevel();
} }

View File

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.email.service; package com.android.emailcommon.service;
oneway interface IEmailServiceCallback { oneway interface IEmailServiceCallback {
/* /*

View File

@ -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;
}
}
}

View File

@ -28,7 +28,7 @@ import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message; import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns; import com.android.email.provider.EmailContent.MessageColumns;
import com.android.email.provider.EmailContent.SyncColumns; 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.HttpResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;

View File

@ -34,9 +34,9 @@ import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message; import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns; import com.android.email.provider.EmailContent.MessageColumns;
import com.android.email.provider.EmailContent.SyncColumns; import com.android.email.provider.EmailContent.SyncColumns;
import com.android.email.service.EmailServiceConstants; import com.android.emailcommon.service.EmailServiceConstants;
import com.android.email.service.EmailServiceProxy; import com.android.emailcommon.service.EmailServiceProxy;
import com.android.email.service.EmailServiceStatus; import com.android.emailcommon.service.EmailServiceStatus;
import com.android.exchange.adapter.AbstractSyncAdapter; import com.android.exchange.adapter.AbstractSyncAdapter;
import com.android.exchange.adapter.AccountSyncAdapter; import com.android.exchange.adapter.AccountSyncAdapter;
import com.android.exchange.adapter.CalendarSyncAdapter; import com.android.exchange.adapter.CalendarSyncAdapter;

View File

@ -23,6 +23,7 @@ import com.android.email.NotificationController;
import com.android.email.Utility; import com.android.email.Utility;
import com.android.email.mail.transport.SSLUtils; import com.android.email.mail.transport.SSLUtils;
import com.android.email.provider.EmailContent; 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.Account;
import com.android.email.provider.EmailContent.Attachment; import com.android.email.provider.EmailContent.Attachment;
import com.android.email.provider.EmailContent.HostAuth; 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.MailboxColumns;
import com.android.email.provider.EmailContent.Message; import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.SyncColumns; 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.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.CalendarSyncAdapter;
import com.android.exchange.adapter.ContactsSyncAdapter; import com.android.exchange.adapter.ContactsSyncAdapter;
import com.android.exchange.utility.FileLogger; import com.android.exchange.utility.FileLogger;
@ -67,21 +68,21 @@ import android.database.ContentObserver;
import android.database.Cursor; import android.database.Cursor;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.Uri; import android.net.Uri;
import android.net.NetworkInfo.State;
import android.os.Bundle; import android.os.Bundle;
import android.os.Debug; import android.os.Debug;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Process; import android.os.Process;
import android.os.RemoteCallbackList; import android.os.RemoteCallbackList;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.PowerManager.WakeLock;
import android.provider.Calendar; import android.provider.Calendar;
import android.provider.ContactsContract;
import android.provider.Calendar.Calendars; import android.provider.Calendar.Calendars;
import android.provider.Calendar.Events; import android.provider.Calendar.Events;
import android.provider.ContactsContract;
import android.util.Log; import android.util.Log;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -462,6 +463,11 @@ public class ExchangeService extends Service implements Runnable {
// Delete the data // Delete the data
ExchangeService.deleteAccountPIMData(accountId); ExchangeService.deleteAccountPIMData(accountId);
} }
@Override
public int getApiLevel() throws RemoteException {
return Api.LEVEL;
}
}; };
private static AccountList collectEasAccounts(Context context, AccountList accounts) { private static AccountList collectEasAccounts(Context context, AccountList accounts) {

View File

@ -26,6 +26,7 @@ import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.ProviderTestUtils; import com.android.email.provider.ProviderTestUtils;
import com.android.email.service.AttachmentDownloadService.DownloadRequest; import com.android.email.service.AttachmentDownloadService.DownloadRequest;
import com.android.email.service.AttachmentDownloadService.DownloadSet; import com.android.email.service.AttachmentDownloadService.DownloadSet;
import com.android.emailcommon.service.EmailServiceStatus;
import android.content.Context; import android.content.Context;