Prepare for separate Exchange application

* Remove reference to certificate in Android.mk (the certs will
  be derived from the directory, i.e. Exchange vs ExchangeGoogle)
* Remove sharedUserId and process name from manifest
* Change loadAttachment to use AttachmentProvider to open attachment
  files for writing
* Always retrieve deviceId from Email app

Bug: 3442973
Change-Id: I70ddb4d2971e481b0d4def09944e54d23ef431ec
diff --git a/Android.mk b/Android.mk
index 96da6c1..443727e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,9 +21,6 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-common com.android.emailcommon
 
-# STOPSHIP Use appropriate cert (the Google app cert for now)
-LOCAL_CERTIFICATE := vendor/unbundled_google/libraries/certs/app
-
 LOCAL_PACKAGE_NAME := Exchange
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b46bfda..0ce6817 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -19,7 +19,7 @@
     package="com.android.exchange"
     android:versionCode="300000"
     android:versionName="3.0"
-    android:sharedUserId="com.android.email" >
+     >
 
     <uses-permission
         android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
@@ -70,7 +70,6 @@
         android:label="@string/account_setup_account_type_exchange_action"
         android:name="Exchange"
         android:theme="@android:style/Theme.Holo.Light"
-        android:process="com.android.email"
         >
 
         <receiver
diff --git a/src/com/android/exchange/EasOutboxService.java b/src/com/android/exchange/EasOutboxService.java
index d16967f..7968019 100644
--- a/src/com/android/exchange/EasOutboxService.java
+++ b/src/com/android/exchange/EasOutboxService.java
@@ -17,8 +17,8 @@
 
 package com.android.exchange;
 
-import com.android.emailcommon.mail.MessagingException;
 import com.android.emailcommon.internet.Rfc822Output;
+import com.android.emailcommon.mail.MessagingException;
 import com.android.emailcommon.provider.EmailContent.Account;
 import com.android.emailcommon.provider.EmailContent.Body;
 import com.android.emailcommon.provider.EmailContent.BodyColumns;
@@ -197,7 +197,7 @@
         setupService();
         File cacheDir = mContext.getCacheDir();
         try {
-            mDeviceId = ExchangeService.getDeviceId();
+            mDeviceId = ExchangeService.getDeviceId(mContext);
             Cursor c = mContext.getContentResolver().query(Message.CONTENT_URI,
                     Message.ID_COLUMN_PROJECTION, MAILBOX_KEY_AND_NOT_SEND_FAILED,
                     new String[] {Long.toString(mMailbox.mId)}, null);
diff --git a/src/com/android/exchange/EasSyncService.java b/src/com/android/exchange/EasSyncService.java
index a8275d5..380e6f3 100644
--- a/src/com/android/exchange/EasSyncService.java
+++ b/src/com/android/exchange/EasSyncService.java
@@ -35,6 +35,7 @@
 import com.android.emailcommon.service.EmailServiceProxy;
 import com.android.emailcommon.service.EmailServiceStatus;
 import com.android.emailcommon.service.PolicySet;
+import com.android.emailcommon.utility.AttachmentUtilities;
 import com.android.emailcommon.utility.Utility;
 import com.android.exchange.adapter.AbstractSyncAdapter;
 import com.android.exchange.adapter.AccountSyncAdapter;
@@ -93,9 +94,10 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.lang.Thread.State;
 import java.net.URI;
 import java.security.cert.CertificateException;
@@ -852,7 +854,7 @@
                 svc.mPassword = ha.mPassword;
                 svc.mSsl = (ha.mFlags & HostAuth.FLAG_SSL) != 0;
                 svc.mTrustSsl = (ha.mFlags & HostAuth.FLAG_TRUST_ALL) != 0;
-                svc.mDeviceId = ExchangeService.getDeviceId();
+                svc.mDeviceId = ExchangeService.getDeviceId(context);
                 svc.mAccount = acct;
                 Serializer s = new Serializer();
                 s.start(Tags.SEARCH_SEARCH).start(Tags.SEARCH_STORE);
@@ -967,15 +969,16 @@
             if (status == HttpStatus.SC_OK) {
                 int len = (int)entity.getContentLength();
                 InputStream is = entity.getContent();
-                File f = (req.mDestination != null) ? new File(req.mDestination) :
-                    createUniqueFileInternal(req.mDestination, att.mFileName);
-                if (f != null) {
-                    // Ensure that the target directory exists
-                    File destDir = f.getParentFile();
-                    if (!destDir.exists()) {
-                        destDir.mkdirs();
-                    }
-                    FileOutputStream os = new FileOutputStream(f);
+                OutputStream os = null;
+                Uri attachmentUri = AttachmentUtilities.getAttachmentUri(att.mAccountKey, att.mId);
+                String fileName = null;
+                try {
+                    os = mContentResolver.openOutputStream(attachmentUri);
+                    userLog("Attachment filename retrieved as: " + fileName);
+                } catch (FileNotFoundException e) {
+                    userLog("Can't get attachment; write file not found?");
+                }
+                if (os != null) {
                     // len > 0 means that Content-Length was set in the headers
                     // len < 0 means "chunked" transfer-encoding
                     if (len != 0) {
@@ -1023,11 +1026,8 @@
 
                     // EmailProvider will throw an exception if update an unsaved attachment
                     if (att.isSaved()) {
-                        String contentUriString = (req.mContentUriString != null) ?
-                            req.mContentUriString :
-                            "file://" + f.getAbsolutePath();
                         ContentValues cv = new ContentValues();
-                        cv.put(AttachmentColumns.CONTENT_URI, contentUriString);
+                        cv.put(AttachmentColumns.CONTENT_URI, attachmentUri.toString());
                         att.update(mContext, cv);
                         doStatusCallback(msg.mId, att.mId, EmailServiceStatus.SUCCESS);
                     }
@@ -2385,7 +2385,7 @@
 
         // Whether or not we're the account mailbox
         try {
-            mDeviceId = ExchangeService.getDeviceId();
+            mDeviceId = ExchangeService.getDeviceId(mContext);
             if ((mMailbox == null) || (mAccount == null)) {
                 return;
             } else if (mMailbox.mType == Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {
diff --git a/src/com/android/exchange/ExchangeService.java b/src/com/android/exchange/ExchangeService.java
index f62d926..9a6c78c 100644
--- a/src/com/android/exchange/ExchangeService.java
+++ b/src/com/android/exchange/ExchangeService.java
@@ -18,8 +18,6 @@
 package com.android.exchange;
 
 import com.android.emailcommon.Api;
-import com.android.emailcommon.Device;
-import com.android.emailcommon.Logging;
 import com.android.emailcommon.TempDirectory;
 import com.android.emailcommon.provider.EmailContent;
 import com.android.emailcommon.provider.EmailContent.Account;
@@ -85,11 +83,6 @@
 import android.provider.ContactsContract;
 import android.util.Log;
 
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -385,13 +378,12 @@
             stopManualSync(mailboxId);
         }
 
-        public void loadAttachment(long attachmentId, String destinationFile,
-                String contentUriString, boolean background) throws RemoteException {
-            if (Eas.USER_LOG) {
-                Log.d(TAG, "loadAttachment: " + attachmentId + " to " + destinationFile);
-            }
+        public void loadAttachment(long attachmentId, boolean background) throws RemoteException {
             Attachment att = Attachment.restoreAttachmentWithId(ExchangeService.this, attachmentId);
-            sendMessageRequest(new PartRequest(att, destinationFile, contentUriString));
+            if (Eas.USER_LOG) {
+                Log.d(TAG, "loadAttachment " + attachmentId + ": " + att.mFileName);
+            }
+            sendMessageRequest(new PartRequest(att, null, null));
         }
 
         public void updateFolderList(long accountId) throws RemoteException {
@@ -1081,56 +1073,19 @@
     /**
      * EAS requires a unique device id, so that sync is possible from a variety of different
      * devices (e.g. the syncKey is specific to a device)  If we're on an emulator or some other
-     * device that doesn't provide one, we can create it as droid<n> where <n> is system time.
+     * device that doesn't provide one, we can create it as "device".
      * This would work on a real device as well, but it would be better to use the "real" id if
      * it's available
      */
-    static public String getDeviceId() throws IOException {
-        return getDeviceId(null);
-    }
-
-    static public synchronized String getDeviceId(Context context) throws IOException {
+    static public String getDeviceId(Context context) throws IOException {
         if (sDeviceId == null) {
-            sDeviceId = getDeviceIdInternal(context);
-        }
-        return sDeviceId;
-    }
-
-    static private String getDeviceIdInternal(Context context) throws IOException {
-        if (INSTANCE == null && context == null) {
-            throw new IOException("No context for getDeviceId");
-        } else if (context == null) {
-            context = INSTANCE;
-        }
-
-        File f = context.getFileStreamPath("deviceName");
-        BufferedReader rdr = null;
-        String id;
-        if (f.exists()) {
-            if (f.canRead()) {
-                rdr = new BufferedReader(new FileReader(f), 128);
-                id = rdr.readLine();
-                rdr.close();
-                return id;
-            } else {
-                Log.w(Logging.LOG_TAG, f.getAbsolutePath() + ": File exists, but can't read?" +
-                        "  Trying to remove.");
-                if (!f.delete()) {
-                    Log.w(Logging.LOG_TAG, "Remove failed. Tring to overwrite.");
-                }
+            try {
+                sDeviceId = new AccountServiceProxy(context).getDeviceId();
+                alwaysLog("Received deviceId from Email app: " + sDeviceId);
+            } catch (RemoteException e) {
             }
         }
-        BufferedWriter w = new BufferedWriter(new FileWriter(f), 128);
-        final String consistentDeviceId = Device.getConsistentDeviceId(context);
-        if (consistentDeviceId != null) {
-            // Use different prefix from random IDs.
-            id = "androidc" + consistentDeviceId;
-        } else {
-            id = "android" + System.currentTimeMillis();
-        }
-        w.write(id);
-        w.close();
-        return id;
+        return sDeviceId;
     }
 
     @Override
@@ -1738,14 +1693,6 @@
             if (sStop) {
                 return;
             }
-            if (sDeviceId == null) {
-                try {
-                    getDeviceId(this);
-                } catch (IOException e) {
-                    // We can't run in this situation
-                    throw new RuntimeException(e);
-                }
-            }
         }
     }
 
@@ -1761,6 +1708,19 @@
                         log("!!! Email application not found; stopping self");
                         stopSelf();
                     }
+                    if (sDeviceId == null) {
+                        try {
+                            String deviceId = getDeviceId(ExchangeService.this);
+                            if (deviceId != null) {
+                                sDeviceId = deviceId;
+                            }
+                        } catch (IOException e) {
+                        }
+                        if (sDeviceId == null) {
+                            log("!!! deviceId not determined; stopping self");
+                            stopSelf();
+                        }
+                    }
                     // Restore accounts, if it has not happened already
                     try {
                         new AccountServiceProxy(ExchangeService.this).restoreAccountsIfNeeded();