/**
  * If values are passed in, replaces any cached cursor with one containing new values, and then
  * closes the previously cached one (if any, and if not in use) If values are not passed in,
  * removes the row from cache If the row was locked, unlock it
  *
  * @param id the id of the row
  * @param values new ContentValues for the row (or null if row should simply be removed)
  * @param wasLocked whether or not the row was locked; if so, the lock will be removed
  */
 private void unlockImpl(String id, ContentValues values, boolean wasLocked) {
   Cursor c = get(id);
   if (c != null) {
     if (MailActivityEmail.DEBUG && DEBUG_CACHE) {
       LogUtils.d(mLogTag, "=========== Unlocking cache for: " + id);
     }
     if (values != null && !sLockCache) {
       MatrixCursor cursor = getMatrixCursor(id, mBaseProjection, values);
       if (cursor != null) {
         if (MailActivityEmail.DEBUG && DEBUG_CACHE) {
           LogUtils.d(mLogTag, "=========== Recaching with new values: " + id);
         }
         cursor.moveToFirst();
         mLruCache.put(id, cursor);
       } else {
         mLruCache.remove(id);
       }
     } else {
       mLruCache.remove(id);
     }
     // If there are no cursors using the old cached cursor, close it
     if (!sActiveCursors.contains(c)) {
       c.close();
     }
   }
   if (wasLocked) {
     mLockMap.subtract(id);
   }
 }
 public synchronized Cursor putCursorImpl(
     Cursor c, String id, String[] projection, CacheToken token) {
   try {
     if (!token.isValid()) {
       if (MailActivityEmail.DEBUG && DEBUG_CACHE) {
         LogUtils.d(mLogTag, "============ Stale token for " + id);
       }
       mStats.mStaleCount++;
       return c;
     }
     if (c != null && Arrays.equals(projection, mBaseProjection) && !sLockCache) {
       if (MailActivityEmail.DEBUG && DEBUG_CACHE) {
         LogUtils.d(mLogTag, "============ Caching cursor for: " + id);
       }
       // If we've already cached this cursor, invalidate the older one
       Cursor existingCursor = get(id);
       if (existingCursor != null) {
         unlockImpl(id, null, false);
       }
       mLruCache.put(id, c);
       return new CachedCursor(c, this, id);
     }
     return c;
   } finally {
     mTokenList.remove(token);
   }
 }
 /** M: Wipe the records from MessageStateChange table which belong to mMailbox */
 private void wipeMessageStateChanges() {
   Cursor c =
       mContentResolver.query(
           Message.CONTENT_URI,
           new String[] {MessageColumns.MESSAGE_ID},
           MessageColumns.MAILBOX_KEY + "=?",
           new String[] {String.valueOf(mMailbox.mId)},
           null);
   if (c == null) {
     LogUtils.i(Eas.BSK_TAG, "Get message cursor failed");
     return;
   }
   try {
     ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
     while (c.moveToNext()) {
       ops.add(
           ContentProviderOperation.newDelete(MessageStateChange.CONTENT_URI)
               .withSelection(
                   MessageChangeLogTable.MESSAGE_KEY + "=?", new String[] {c.getString(0)})
               .build());
       applyBatchIfNeeded(ops, MAX_OPS_PER_BATCH, false);
     }
     applyBatchIfNeeded(ops, MAX_OPS_PER_BATCH, true);
   } catch (RemoteException e) {
     LogUtils.i(Eas.BSK_TAG, "RemoteException when wipeMessageStateChanges");
   } catch (OperationApplicationException e) {
     LogUtils.i(Eas.BSK_TAG, "OperationApplicationException when wipeMessageStateChanges");
   } finally {
     c.close();
   }
 }
Beispiel #4
0
 // invalidate a rectangle relative to the view's coordinate system all the way up the view
 // hierarchy
 public static void invalidateGlobalRegion(View view, RectF childBounds) {
   // childBounds.offset(view.getTranslationX(), view.getTranslationY());
   if (DEBUG_INVALIDATE) LogUtils.v(TAG, "-------------");
   while (view.getParent() != null && view.getParent() instanceof View) {
     view = (View) view.getParent();
     view.getMatrix().mapRect(childBounds);
     view.invalidate(
         (int) Math.floor(childBounds.left),
         (int) Math.floor(childBounds.top),
         (int) Math.ceil(childBounds.right),
         (int) Math.ceil(childBounds.bottom));
     if (DEBUG_INVALIDATE) {
       LogUtils.v(
           TAG,
           "INVALIDATE("
               + (int) Math.floor(childBounds.left)
               + ","
               + (int) Math.floor(childBounds.top)
               + ","
               + (int) Math.ceil(childBounds.right)
               + ","
               + (int) Math.ceil(childBounds.bottom));
     }
   }
 }
  @Override
  public void loadMore(long messageId) throws RemoteException {
    /// M: We Can't load more in low storage state @{
    if (StorageLowState.checkIfStorageLow(mContext)) {
      LogUtils.e(Logging.LOG_TAG, "Can't load more due to low storage");
      return;
    }
    /// @}
    // Load a message for view...
    try {
      // 1. Resample the message, in case it disappeared or synced while
      // this command was in queue
      final EmailContent.Message message =
          EmailContent.Message.restoreMessageWithId(mContext, messageId);
      if (message == null) {
        return;
      }
      if (message.mFlagLoaded == EmailContent.Message.FLAG_LOADED_COMPLETE) {
        // We should NEVER get here
        return;
      }

      // 2. Open the remote folder.
      // TODO combine with common code in loadAttachment
      final Account account = Account.restoreAccountWithId(mContext, message.mAccountKey);
      final Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, message.mMailboxKey);
      if (account == null || mailbox == null) {
        // mListeners.loadMessageForViewFailed(messageId, "null account or mailbox");
        return;
      }
      TrafficStats.setThreadStatsTag(TrafficFlags.getSyncFlags(mContext, account));

      final Store remoteStore = Store.getInstance(account, mContext);
      final String remoteServerId;
      // If this is a search result, use the protocolSearchInfo field to get the
      // correct remote location
      if (!TextUtils.isEmpty(message.mProtocolSearchInfo)) {
        remoteServerId = message.mProtocolSearchInfo;
      } else {
        remoteServerId = mailbox.mServerId;
      }
      final Folder remoteFolder = remoteStore.getFolder(remoteServerId);
      remoteFolder.open(OpenMode.READ_WRITE);

      // 3. Set up to download the entire message
      final Message remoteMessage = remoteFolder.getMessage(message.mServerId);
      final FetchProfile fp = new FetchProfile();
      fp.add(FetchProfile.Item.BODY);
      remoteFolder.fetch(new Message[] {remoteMessage}, fp, null);

      // 4. Write to provider
      Utilities.copyOneMessageToProvider(
          mContext, remoteMessage, account, mailbox, EmailContent.Message.FLAG_LOADED_COMPLETE);
    } catch (MessagingException me) {
      if (Logging.LOGD) LogUtils.v(Logging.LOG_TAG, "", me);

    } catch (RuntimeException rte) {
      LogUtils.d(Logging.LOG_TAG, "RTE During loadMore");
    }
  }
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    if (!isUserVisible()) {
      // Unclear how this is happening. Current theory is that this fragment was scheduled
      // to be removed, but the remove transaction failed. When the Activity is later
      // restored, the FragmentManager restores this fragment, but Fragment.mMenuVisible is
      // stuck at its initial value (true), which makes this zombie fragment eligible for
      // menu item clicks.
      //
      // Work around this by relying on the (properly restored) extra user visible hint.
      LogUtils.e(
          LOG_TAG, "ACVF ignoring onOptionsItemSelected b/c userVisibleHint is false. f=%s", this);
      if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
        LogUtils.e(LOG_TAG, Utils.dumpFragment(this)); // the dump has '%' chars in it...
      }
      return false;
    }

    boolean handled = false;
    final int itemId = item.getItemId();
    if (itemId == R.id.inside_conversation_unread) {
      markUnread();
      handled = true;
    } else if (itemId == R.id.show_original) {
      showUntransformedConversation();
      handled = true;
    }
    return handled;
  }
 private void refreshEntry(Context context, CacheEntry entry)
     throws IOException, MessagingException {
   LogUtils.d(Logging.LOG_TAG, "AuthenticationCache refreshEntry %d", entry.mAccountId);
   try {
     final AuthenticationResult result =
         mAuthenticator.requestRefresh(context, entry.mProviderId, entry.mRefreshToken);
     // Don't set the refresh token here, it's not returned by the refresh response,
     // so setting it here would make it blank.
     entry.mAccessToken = result.mAccessToken;
     entry.mExpirationTime =
         result.mExpiresInSeconds * DateUtils.SECOND_IN_MILLIS + System.currentTimeMillis();
     saveEntry(context, entry);
   } catch (AuthenticationFailedException e) {
     // This is fatal. Clear the tokens and rethrow the exception.
     LogUtils.d(Logging.LOG_TAG, "authentication failed, clearning");
     clearEntry(context, entry);
     throw e;
   } catch (MessagingException e) {
     LogUtils.d(Logging.LOG_TAG, "messaging exception");
     throw e;
   } catch (IOException e) {
     LogUtils.d(Logging.LOG_TAG, "IO exception");
     throw e;
   }
 }
  /**
   * Add a single attachment part to the message
   *
   * <p>This will skip adding attachments if they are already found in the attachments table. The
   * heuristic for this will fail (false-positive) if two identical attachments are included in a
   * single POP3 message. TODO: Fix that, by (elsewhere) simulating an mLocation value based on the
   * attachments position within the list of multipart/mixed elements. This would make every POP3
   * attachment unique, and might also simplify the code (since we could just look at the positions,
   * and ignore the filename, etc.)
   *
   * <p>TODO: Take a closer look at encoding and deal with it if necessary.
   *
   * @param context a context for file operations
   * @param localMessage the attachments will be built against this message
   * @param part a single attachment part from POP or IMAP
   */
  public static void addOneAttachment(
      final Context context, final EmailContent.Message localMessage, final Part part)
      throws MessagingException, IOException {
    final Attachment localAttachment = mimePartToAttachment(part);
    localAttachment.mMessageKey = localMessage.mId;
    localAttachment.mAccountKey = localMessage.mAccountKey;

    if (DEBUG_ATTACHMENTS) {
      LogUtils.d(Logging.LOG_TAG, "Add attachment " + localAttachment);
    }

    // To prevent duplication - do we already have a matching attachment?
    // The fields we'll check for equality are:
    //  mFileName, mMimeType, mContentId, mMessageKey, mLocation
    // NOTE:  This will false-positive if you attach the exact same file, twice, to a POP3
    // message.  We can live with that - you'll get one of the copies.
    final Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId);
    final Cursor cursor =
        context.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, null, null, null);
    boolean attachmentFoundInDb = false;
    try {
      while (cursor.moveToNext()) {
        final Attachment dbAttachment = new Attachment();
        dbAttachment.restore(cursor);
        // We test each of the fields here (instead of in SQL) because they may be
        // null, or may be strings.
        if (!TextUtils.equals(dbAttachment.mFileName, localAttachment.mFileName)
            || !TextUtils.equals(dbAttachment.mMimeType, localAttachment.mMimeType)
            || !TextUtils.equals(dbAttachment.mContentId, localAttachment.mContentId)
            || !TextUtils.equals(dbAttachment.mLocation, localAttachment.mLocation)) {
          continue;
        }
        // We found a match, so use the existing attachment id, and stop looking/looping
        attachmentFoundInDb = true;
        localAttachment.mId = dbAttachment.mId;
        if (DEBUG_ATTACHMENTS) {
          LogUtils.d(Logging.LOG_TAG, "Skipped, found db attachment " + dbAttachment);
        }
        break;
      }
    } finally {
      cursor.close();
    }

    // Save the attachment (so far) in order to obtain an id
    if (!attachmentFoundInDb) {
      localAttachment.save(context);
    }

    // If an attachment body was actually provided, we need to write the file now
    saveAttachmentBody(context, part, localAttachment, localMessage.mAccountKey);

    if (localMessage.mAttachments == null) {
      localMessage.mAttachments = new ArrayList<Attachment>();
    }
    localMessage.mAttachments.add(localAttachment);
    localMessage.mFlagAttachment = true;
  }
    @Override
    public void onLoadFinished(
        Loader<ObjectCursor<ConversationMessage>> loader, ObjectCursor<ConversationMessage> data) {
      // ignore truly duplicate results
      // this can happen when restoring after rotation
      if (mCursor == data) {
        return;
      } else {
        final MessageCursor messageCursor = (MessageCursor) data;

        // bind the cursor to this fragment so it can access to the current list controller
        messageCursor.setController(AbstractConversationViewFragment.this);

        if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
          LogUtils.d(LOG_TAG, "LOADED CONVERSATION= %s", messageCursor.getDebugDump());
        }

        // We have no messages: exit conversation view.
        if (messageCursor.getCount() == 0
            && (!CursorStatus.isWaitingForResults(messageCursor.getStatus()) || mIsDetached)) {
          if (mUserVisible) {
            onError();
          } else {
            // we expect that the pager adapter will remove this
            // conversation fragment on its own due to a separate
            // conversation cursor update (we might get here if the
            // message list update fires first. nothing to do
            // because we expect to be torn down soon.)
            LogUtils.i(
                LOG_TAG,
                "CVF: offscreen conv has no messages, ignoring update"
                    + " in anticipation of conv cursor update. c=%s",
                mConversation.uri);
          }
          // existing mCursor will imminently be closed, must stop referencing it
          // since we expect to be kicked out soon, it doesn't matter what mCursor
          // becomes
          mCursor = null;
          return;
        }

        // ignore cursors that are still loading results
        if (!messageCursor.isLoaded()) {
          // existing mCursor will imminently be closed, must stop referencing it
          // in this case, the new cursor is also no good, and since don't expect to get
          // here except in initial load situations, it's safest to just ensure the
          // reference is null
          mCursor = null;
          return;
        }
        final MessageCursor oldCursor = mCursor;
        mCursor = messageCursor;
        onMessageCursorLoadFinished(loader, mCursor, oldCursor);
      }
    }
 /*package*/ boolean remove(CacheToken token) {
   boolean result = super.remove(token);
   if (MailActivityEmail.DEBUG && DEBUG_TOKENS) {
     if (result) {
       LogUtils.d(mLogTag, "============ Removing token for: " + token.mId);
     } else {
       LogUtils.d(mLogTag, "============ No token found for: " + token.mId);
     }
   }
   return result;
 }
  public static void dumpStats() {
    Statistics totals = new Statistics("Totals");

    for (ContentCache cache : sContentCaches) {
      if (cache != null) {
        LogUtils.d(cache.mName, cache.mStats.toString());
        totals.addCacheStatistics(cache);
      }
    }
    LogUtils.d(totals.mName, totals.toString());
  }
 private static Bitmap createImageThumbnail(InputStream data) {
   try {
     Bitmap bitmap = BitmapFactory.decodeStream(data);
     return bitmap;
   } catch (OutOfMemoryError oome) {
     LogUtils.d(Logging.LOG_TAG, "createImageThumbnail failed with " + oome.getMessage());
     return null;
   } catch (Exception e) {
     LogUtils.d(Logging.LOG_TAG, "createImageThumbnail failed with " + e.getMessage());
     return null;
   }
 }
 private static void finishAccountManagerBlocker(AccountManagerFuture<?> future) {
   try {
     // Note: All of the potential errors are simply logged
     // here, as there is nothing to actually do about them.
     future.getResult();
   } catch (OperationCanceledException e) {
     LogUtils.w(Logging.LOG_TAG, e.toString());
   } catch (AuthenticatorException e) {
     LogUtils.w(Logging.LOG_TAG, e.toString());
   } catch (IOException e) {
     LogUtils.w(Logging.LOG_TAG, e.toString());
   }
 }
  /**
   * Set the requested security level based on the aggregate set of requests. If the set is empty,
   * we release our device administration. If the set is non-empty, we only proceed if we are
   * already active as an admin.
   */
  public void setActivePolicies() {
    DevicePolicyManager dpm = getDPM();
    // compute aggregate set of policies
    Policy aggregatePolicy = getAggregatePolicy();
    // if empty set, detach from policy manager
    if (aggregatePolicy == Policy.NO_POLICY) {
      if (DebugUtils.DEBUG) {
        LogUtils.d(TAG, "setActivePolicies: none, remove admin");
      }
      dpm.removeActiveAdmin(mAdminName);
    } else if (isActiveAdmin()) {
      if (DebugUtils.DEBUG) {
        LogUtils.d(TAG, "setActivePolicies: " + aggregatePolicy);
      }
      // set each policy in the policy manager
      // password mode & length
      dpm.setPasswordQuality(mAdminName, aggregatePolicy.getDPManagerPasswordQuality());
      dpm.setPasswordMinimumLength(mAdminName, aggregatePolicy.mPasswordMinLength);
      // screen lock time
      dpm.setMaximumTimeToLock(mAdminName, aggregatePolicy.mMaxScreenLockTime * 1000);
      // local wipe (failed passwords limit)
      dpm.setMaximumFailedPasswordsForWipe(mAdminName, aggregatePolicy.mPasswordMaxFails);
      // password expiration (days until a password expires).  API takes mSec.
      dpm.setPasswordExpirationTimeout(
          mAdminName, aggregatePolicy.getDPManagerPasswordExpirationTimeout());
      // password history length (number of previous passwords that may not be reused)
      dpm.setPasswordHistoryLength(mAdminName, aggregatePolicy.mPasswordHistory);
      // password minimum complex characters.
      // Note, in Exchange, "complex chars" simply means "non alpha", but in the DPM,
      // setting the quality to complex also defaults min symbols=1 and min numeric=1.
      // We always / safely clear minSymbols & minNumeric to zero (there is no policy
      // configuration in which we explicitly require a minimum number of digits or symbols.)
      dpm.setPasswordMinimumSymbols(mAdminName, 0);
      dpm.setPasswordMinimumNumeric(mAdminName, 0);
      dpm.setPasswordMinimumNonLetter(mAdminName, aggregatePolicy.mPasswordComplexChars);
      // Device capabilities
      try {
        // If we are running in a managed policy, it is a securityException to even
        // call setCameraDisabled(), if is disabled is false. We have to swallow
        // the exception here.
        dpm.setCameraDisabled(mAdminName, aggregatePolicy.mDontAllowCamera);
      } catch (SecurityException e) {
        LogUtils.d(TAG, "SecurityException in setCameraDisabled, nothing changed");
      }

      // encryption required
      dpm.setStorageEncryption(mAdminName, aggregatePolicy.mRequireEncryption);
    }
  }
  /** Writes a single line to the server using \r\n termination. */
  public void writeLine(String s, String sensitiveReplacement) throws IOException {
    if (MailActivityEmail.DEBUG) {
      if (sensitiveReplacement != null && !Logging.DEBUG_SENSITIVE) {
        LogUtils.d(Logging.LOG_TAG, ">>> " + sensitiveReplacement);
      } else {
        LogUtils.d(Logging.LOG_TAG, ">>> " + s);
      }
    }

    OutputStream out = getOutputStream();
    out.write(s.getBytes());
    out.write('\r');
    out.write('\n');
    out.flush();
  }
  @Override
  public void onCreate(Bundle savedState) {
    super.onCreate(savedState);

    parseArguments();
    setBaseUri();

    LogUtils.d(LOG_TAG, "onCreate in ConversationViewFragment (this=%s)", this);
    // Not really, we just want to get a crack to store a reference to the change_folder item
    setHasOptionsMenu(true);

    if (savedState != null) {
      mViewState = savedState.getParcelable(BUNDLE_VIEW_STATE);
      mUserVisible = savedState.getBoolean(BUNDLE_USER_VISIBLE);
      mIsDetached = savedState.getBoolean(BUNDLE_DETACHED, false);
      mHasConversationBeenTransformed =
          savedState.getBoolean(BUNDLE_KEY_HAS_CONVERSATION_BEEN_TRANSFORMED, false);
      mHasConversationTransformBeenReverted =
          savedState.getBoolean(BUNDLE_KEY_HAS_CONVERSATION_BEEN_REVERTED, false);
    } else {
      mViewState = getNewViewState();
      mHasConversationBeenTransformed = false;
      mHasConversationTransformBeenReverted = false;
    }
  }
Beispiel #17
0
 public String getSimplifiedName() {
   String str2;
   if (this.mSimplifiedName == null) {
     if ((!TextUtils.isEmpty(this.mName)) || (TextUtils.isEmpty(this.mAddress))) break label74;
     int j = this.mAddress.indexOf('@');
     if (j == -1) break label67;
     str2 = this.mAddress.substring(0, j);
     this.mSimplifiedName = str2;
   }
   while (true) {
     return this.mSimplifiedName;
     label67:
     str2 = "";
     break;
     label74:
     if (!TextUtils.isEmpty(this.mName)) {
       for (int i = this.mName.indexOf(' '); (i > 0) && (this.mName.charAt(i - 1) == ','); i--) ;
       if (i < 1) ;
       for (String str1 = this.mName; ; str1 = this.mName.substring(0, i)) {
         this.mSimplifiedName = str1;
         break;
       }
     }
     LogUtils.w(LOG_TAG, "Unable to get a simplified name", new Object[0]);
     this.mSimplifiedName = "";
   }
 }
 private CacheEntry getEntry(Context context, Account account) {
   CacheEntry entry;
   if (account.isSaved() && !account.isTemporary()) {
     entry = mCache.get(account.mId);
     if (entry == null) {
       LogUtils.d(Logging.LOG_TAG, "initializing entry from database");
       final HostAuth hostAuth = account.getOrCreateHostAuthRecv(context);
       final Credential credential = hostAuth.getOrCreateCredential(context);
       entry =
           new CacheEntry(
               account.mId,
               credential.mProviderId,
               credential.mAccessToken,
               credential.mRefreshToken,
               credential.mExpiration);
       mCache.put(account.mId, entry);
     }
   } else {
     // This account is temporary, just create a temporary entry. Don't store
     // it in the cache, it won't be findable because we don't yet have an account Id.
     final HostAuth hostAuth = account.getOrCreateHostAuthRecv(context);
     final Credential credential = hostAuth.getCredential(context);
     entry =
         new CacheEntry(
             account.mId,
             credential.mProviderId,
             credential.mAccessToken,
             credential.mRefreshToken,
             credential.mExpiration);
   }
   return entry;
 }
 public static void alwaysLog(String str) {
   if (!Eas.USER_LOG) {
     LogUtils.d(TAG, str);
   } else {
     log(str);
   }
 }
 public void render(Attachment paramAttachment, boolean paramBoolean) {
   Attachment localAttachment = this.mAttachment;
   this.mAttachment = paramAttachment;
   this.mActionHandler.setAttachment(this.mAttachment);
   if (!paramAttachment.isDownloading()) ;
   for (boolean bool = false; ; bool = this.mSaveClicked) {
     this.mSaveClicked = bool;
     String str = LOG_TAG;
     Object[] arrayOfObject = new Object[6];
     arrayOfObject[0] = paramAttachment.name;
     arrayOfObject[1] = Integer.valueOf(paramAttachment.state);
     arrayOfObject[2] = Integer.valueOf(paramAttachment.destination);
     arrayOfObject[3] = Integer.valueOf(paramAttachment.downloadedSize);
     arrayOfObject[4] = paramAttachment.contentUri;
     arrayOfObject[5] = paramAttachment.contentType;
     LogUtils.d(
         str,
         "got attachment list row: name=%s state/dest=%d/%d dled=%d contentUri=%s MIME=%s",
         arrayOfObject);
     if ((localAttachment == null)
         || (!TextUtils.equals(paramAttachment.name, localAttachment.name)))
       this.mTitle.setText(paramAttachment.name);
     if ((localAttachment == null) || (paramAttachment.size != localAttachment.size)) {
       this.mAttachmentSizeText =
           AttachmentUtils.convertToHumanReadableSize(getContext(), paramAttachment.size);
       this.mDisplayType = AttachmentUtils.getDisplayType(getContext(), paramAttachment);
       updateSubtitleText(null);
     }
     updateActions();
     this.mActionHandler.updateStatus(paramBoolean);
     return;
   }
 }
 @Deprecated
 @Override
 public void startSync(long mailboxId, boolean userRequest, int deltaMessageCount)
     throws RemoteException {
   final Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mailboxId);
   if (mailbox == null) return;
   final Account account = Account.restoreAccountWithId(mContext, mailbox.mAccountKey);
   if (account == null) return;
   final EmailServiceInfo info = EmailServiceUtils.getServiceInfoForAccount(mContext, account.mId);
   final android.accounts.Account acct =
       new android.accounts.Account(account.mEmailAddress, info.accountType);
   final Bundle extras = Mailbox.createSyncBundle(mailboxId);
   if (userRequest) {
     extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
     extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
     extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
   }
   if (deltaMessageCount != 0) {
     extras.putInt(Mailbox.SYNC_EXTRA_DELTA_MESSAGE_COUNT, deltaMessageCount);
   }
   ContentResolver.requestSync(acct, EmailContent.AUTHORITY, extras);
   LogUtils.i(
       Logging.LOG_TAG,
       "requestSync EmailServiceStub startSync %s, %s",
       account.toString(),
       extras.toString());
 }
Beispiel #22
0
    private boolean parseStore() throws IOException {
      EmailSyncAdapter adapter = new EmailSyncAdapter(mService);
      EasEmailSyncParser parser = new EasEmailSyncParser(this, adapter);
      ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
      boolean res = false;

      while (nextTag(Tags.SEARCH_STORE) != END) {
        if (tag == Tags.SEARCH_STATUS) {
          getValue();
        } else if (tag == Tags.SEARCH_TOTAL) {
          mTotalResults = getValueInt();
        } else if (tag == Tags.SEARCH_RESULT) {
          parseResult(parser, ops);
        } else {
          skipTag();
        }
      }

      try {
        adapter.mContentResolver.applyBatch(EmailContent.AUTHORITY, ops);
        /// M: get the current result count.
        mCurrentResults = ops.size();
        if (Eas.USER_LOG) {
          mService.userLog("Saved " + ops.size() + " search results");
        }
      } catch (RemoteException e) {
        LogUtils.d(Logging.LOG_TAG, "RemoteException while saving search results.");
      } catch (OperationApplicationException e) {
      }

      return res;
    }
  /**
   * Parse a message from the server stream.
   *
   * @return the parsed Message
   * @throws IOException
   */
  private EmailContent.Message addParser(final int endingTag)
      throws IOException, CommandStatusException {
    EmailContent.Message msg = new EmailContent.Message();
    msg.mAccountKey = mAccount.mId;
    msg.mMailboxKey = mMailbox.mId;
    msg.mFlagLoaded = EmailContent.Message.FLAG_LOADED_COMPLETE;
    // Default to 1 (success) in case we don't get this tag
    int status = 1;

    while (nextTag(endingTag) != END) {
      switch (tag) {
        case Tags.SYNC_SERVER_ID:
          msg.mServerId = getValue();
          LogUtils.d(TAG, "ServerId: %s", msg.mServerId);
          break;
        case Tags.SYNC_STATUS:
          status = getValueInt();
          break;
        case Tags.SYNC_APPLICATION_DATA:
          addData(msg, tag);
          break;
        default:
          skipTag();
      }
    }
    // For sync, status 1 = success
    if (status != 1) {
      throw new CommandStatusException(status, msg.mServerId);
    }
    return msg;
  }
 // BEGIN conversation header callbacks
 @Override
 public void onFoldersClicked() {
   if (mChangeFoldersMenuItem == null) {
     LogUtils.e(LOG_TAG, "unable to open 'change folders' dialog for a conversation");
     return;
   }
   mActivity.onOptionsItemSelected(mChangeFoldersMenuItem);
 }
 private void clearEntry(Context context, CacheEntry entry) {
   LogUtils.d(Logging.LOG_TAG, "clearEntry");
   entry.mAccessToken = "";
   entry.mRefreshToken = "";
   entry.mExpirationTime = 0;
   saveEntry(context, entry);
   mCache.remove(entry.mAccountId);
 }
 /**
  * Initializes an {@link AccountObserver} object that receives a call to {@link
  * #onChanged(Account)} when the controller changes the account.
  *
  * @param controller
  */
 public Account initialize(AccountController controller) {
   if (controller == null) {
     LogUtils.wtf(LOG_TAG, "AccountObserver initialized with null controller!");
   }
   mController = controller;
   mController.registerAccountObserver(this);
   return mController.getAccount();
 }
 /**
  * API: Remote wipe (from server). This is final, there is no confirmation. It will only return to
  * the caller if there is an unexpected failure. The wipe includes external storage.
  */
 public void remoteWipe() {
   DevicePolicyManager dpm = getDPM();
   if (dpm.isAdminActive(mAdminName)) {
     dpm.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);
   } else {
     LogUtils.d(Logging.LOG_TAG, "Could not remote wipe because not device admin.");
   }
 }
 public static void log(String tag, String str) {
   if (Eas.USER_LOG) {
     LogUtils.d(tag, str);
     if (Eas.FILE_LOG) {
       FileLogger.log(tag, str);
     }
   }
 }
  protected void onConversationSeen() {
    LogUtils.d(LOG_TAG, "AbstractConversationViewFragment#onConversationSeen()");

    // Ignore unsafe calls made after a fragment is detached from an activity
    final ControllableActivity activity = (ControllableActivity) getActivity();
    if (activity == null) {
      LogUtils.w(LOG_TAG, "ignoring onConversationSeen for conv=%s", mConversation.id);
      return;
    }

    mViewState.setInfoForConversation(mConversation);

    LogUtils.d(
        LOG_TAG, "onConversationSeen() - mSuppressMarkingViewed = %b", mSuppressMarkingViewed);
    // In most circumstances we want to mark the conversation as viewed and read, since the
    // user has read it.  However, if the user has already marked the conversation unread, we
    // do not want a  later mark-read operation to undo this.  So we check this variable which
    // is set in #markUnread() which suppresses automatic mark-read.
    if (!mSuppressMarkingViewed) {
      // mark viewed/read if not previously marked viewed by this conversation view,
      // or if unread messages still exist in the message list cursor
      // we don't want to keep marking viewed on rotation or restore
      // but we do want future re-renders to mark read (e.g. "New message from X" case)
      final MessageCursor cursor = getMessageCursor();
      LogUtils.d(
          LOG_TAG,
          "onConversationSeen() - mConversation.isViewed() = %b, "
              + "cursor null = %b, cursor.isConversationRead() = %b",
          mConversation.isViewed(),
          cursor == null,
          cursor != null && cursor.isConversationRead());
      if (!mConversation.isViewed() || (cursor != null && !cursor.isConversationRead())) {
        // Mark the conversation viewed and read.
        activity
            .getConversationUpdater()
            .markConversationsRead(Arrays.asList(mConversation), true, true);

        // and update the Message objects in the cursor so the next time a cursor update
        // happens with these messages marked read, we know to ignore it
        if (cursor != null && !cursor.isClosed()) {
          cursor.markMessagesRead();
        }
      }
    }
    activity.getListHandler().onConversationSeen();
  }
 public CacheToken add(String id) {
   CacheToken token = new CacheToken(id);
   super.add(token);
   if (MailActivityEmail.DEBUG && DEBUG_TOKENS) {
     LogUtils.d(mLogTag, "============ Taking token for: " + token.mId);
   }
   return token;
 }