/**
   * doDbUpgrade is triggered by someone calling the static method "processPackageReplacedBroadcast"
   *
   * @param cps - a String array containing all the ContentProvider authorities to upgrade
   * @return
   */
  protected boolean doDbUpgrade(final Intent intent) {
    boolean success = false;
    try {
      // First set the global lock on the Base ContentProvider
      LogUtils.i(LogUtils.TAG, "Package has been replaced, perform database upgrades...");
      // PIMContentProviderBase.setMaintenanceLock(cpLock, true);

      // Get the list of content authorities from the Intent extras
      Bundle extras = intent.getExtras();
      String[] cps = extras.getStringArray(CP_LIST);
      if (cps == null) {
        // Nothing to upgrade?
        return success;
      }
      // Write out our current task information to a preference file
      writeActionState(DB_UPGRADE_ACTION, cps);

      // Lock all providers, then upgrade, then unlock
      lockProviders(cps);
      success = upgradeProviders(cps);
      unlockProviders(cps);

    } catch (Exception e) {
      LogUtils.e(LogUtils.TAG, "Database upgrade exception: %s", e.getMessage());
    } finally {
      // Unlock the Base Content Provider
      // PIMContentProviderBase.setMaintenanceLock(cpLock, false);
    }
    LogUtils.i(LogUtils.TAG, "Package has been replaced, perform database upgrades...done");
    return success;
  }
 /**
  * onWakefulHandleIntent called by the WakefullIntent service any time service is called
  *
  * @param intext - the intent we need to handle
  * @return boolean
  */
 @Override
 protected boolean onWakefulHandleIntent(Intent intent) {
   LogUtils.i(
       LogUtils.TAG, "CPMaintenanceService - onWakefulHandleIntent for %s", intent.getAction());
   boolean success = false;
   int action = getAction(intent.getAction());
   switch (action) {
     case DB_MAINT_ACTION:
       break;
     case DB_UPGRADE_ACTION:
       success = doDbUpgrade(intent);
       break;
     case DB_LOCALE_ACTION:
       break;
     case START_ACTION:
       success = doStartupAction(readActionState());
       break;
   }
   if (success) {
     // Overwrite the preference object to indicate we are not in the middle of a task
     writeActionState(UNKNOWN_ACTION, null);
   }
   LogUtils.i(LogUtils.TAG, "Current Maintenance state value is %d", readActionState());
   return success;
 }
    @Override
    public void onPageFinished(WebView view, String url) {
      // Ignore unsafe calls made after a fragment is detached from an activity.
      // This method needs to, for example, get at the loader manager, which needs
      // the fragment to be added.
      if (!isAdded()) {
        LogUtils.d(
            LOG_TAG,
            "ignoring SCVF.onPageFinished, url=%s fragment=%s",
            url,
            SecureConversationViewFragment.this);
        return;
      }

      if (isUserVisible()) {
        onConversationSeen();
      }

      mViewController.dismissLoadingStatus();

      final Set<String> emailAddresses = Sets.newHashSet();
      final List<Address> cacheCopy;
      synchronized (mAddressCache) {
        cacheCopy = ImmutableList.copyOf(mAddressCache.values());
      }
      for (Address addr : cacheCopy) {
        emailAddresses.add(addr.getAddress());
      }
      final ContactLoaderCallbacks callbacks = getContactInfoSource();
      callbacks.setSenders(emailAddresses);
      getLoaderManager().restartLoader(CONTACT_LOADER, Bundle.EMPTY, callbacks);
    }
 private ConversationMessage getMessageFromCursor(MessageCursor cursor) {
   // ignore cursors that are still loading results
   if (cursor == null || !cursor.isLoaded()) {
     LogUtils.i(LOG_TAG, "CONV RENDER: existing cursor is null, rendering from scratch");
     return null;
   }
   if (mActivity == null || mActivity.isFinishing()) {
     // Activity is finishing, just bail.
     return null;
   }
   if (!cursor.moveToFirst()) {
     LogUtils.e(LOG_TAG, "unable to open message cursor");
     return null;
   }
   return cursor.getMessage();
 }
 /**
  * doStartupAction - during startup, check if a previous task was not finished
  *
  * @param action - last action performed
  * @return always returns true
  */
 protected boolean doStartupAction(int lastAction) {
   LogUtils.i(LogUtils.TAG, "Last Maintenance state value is %d", lastAction);
   if (lastAction != UNKNOWN_ACTION) {
     queueUnfinishedTask(lastAction);
   }
   return true;
 }
 /**
  * processPackageReplacedBroadcast should be called when the MY_PACKAGE_REPLACED broadcast is
  * received by this application
  *
  * @param context
  * @param broadcastIntext - the raw broadcast
  * @param cps - a list of ContentProvider Authorities to upgrade
  * @return
  */
 public static void processPackageReplacedBroadcast(
     Context context, Intent broadcastIntent, String[] cps) {
   LogUtils.i(LogUtils.TAG, "CPMaintenanceService - package replaced");
   Intent i = new Intent(context, CPMaintenanceService.class);
   i.setAction(ACTION_PACKAGE_REPLACED_BROADCAST);
   i.putExtra(Intent.EXTRA_INTENT, broadcastIntent);
   i.putExtra(CP_LIST, cps);
   context.startService(i);
 }
 /**
  * queueUnfinishedTask - If the last action did not complete the queue up again
  *
  * @param lastAction - the last action saved to the prefs file
  * @return N/A
  */
 protected void queueUnfinishedTask(int lastAction) {
   switch (lastAction) {
     case DB_UPGRADE_ACTION:
       // Read in the list of authorities
       String[] cps = getCPListFromSharedPrefs();
       // Schedule the upgrade task
       if (cps != null) {
         LogUtils.w(LogUtils.TAG, "Previous Database upgrade task failed:");
         for (String cp : cps) {
           LogUtils.i(LogUtils.TAG, "   upgrading CP: %s", cp);
         }
         processPackageReplacedBroadcast(getApplicationContext(), null, cps);
       } else {
         LogUtils.i(LogUtils.TAG, "Last task was a db upgrade but could not find CP list");
       }
       break;
   }
 }
 /**
  * readActionState - read in state from preference file
  *
  * @return current action from the preference file
  */
 protected int readActionState() {
   int currentAction = UNKNOWN_ACTION;
   try {
     SharedPreferences prefs =
         getApplicationContext().getSharedPreferences(CPMAINT_STATE_PREFERENCE, MODE_PRIVATE);
     if (prefs != null) {
       currentAction = prefs.getInt(CURRENT_TASK, UNKNOWN_ACTION);
     }
   } catch (Exception e) {
     LogUtils.e(LogUtils.TAG, "Unable to get CP Maint action: %s", e.getMessage());
   }
   return currentAction;
 }
 /**
  * writeActionState - write out some state to a preference file
  *
  * @param action - integer
  * @return N/A
  */
 protected void writeActionState(int action, String[] cps) {
   try {
     SharedPreferences prefs =
         getApplicationContext().getSharedPreferences(CPMAINT_STATE_PREFERENCE, MODE_PRIVATE);
     SharedPreferences.Editor editPrefs = prefs.edit();
     editPrefs.putInt(CURRENT_TASK, action);
     if (cps != null) {
       // Save the list of ContentProvider authority strings to the shared pref
       Set<String> mySet = new HashSet<String>(Arrays.asList(cps));
       editPrefs.putStringSet(CP_LIST, mySet);
     }
     editPrefs.commit();
   } catch (Exception e) {
     LogUtils.e(LogUtils.TAG, "Unable to save CP Maint action: %s", e.getMessage());
   }
 }
 /**
  * getActionState - write out some state to a preference file
  *
  * @return current action from the preference file
  */
 protected String[] getCPListFromSharedPrefs() {
   try {
     SharedPreferences prefs =
         getApplicationContext().getSharedPreferences(CPMAINT_STATE_PREFERENCE, MODE_PRIVATE);
     if (prefs != null) {
       Set<String> cps = prefs.getStringSet(CP_LIST, null);
       if (cps != null) {
         // Convert the set to an array of String objects
         return cps.toArray(new String[cps.size()]);
       }
     }
   } catch (Exception e) {
     LogUtils.e(
         LogUtils.TAG, "Cannot get ContentProvider list from preferences: %s", e.getMessage());
   }
   return null;
 }
Ejemplo n.º 11
0
  /**
   * Get the final moves that we want to upsync to the server, setting the status in the DB for all
   * rows to {@link #STATUS_PROCESSING} that are being updated and to {@link #STATUS_FAILED} for any
   * old updates. Messages whose sequence of pending moves results in a no-op (i.e. the message has
   * been moved back to its original folder) have their moves cleared from the DB without any
   * upsync.
   *
   * @param context A {@link Context}.
   * @param accountId The account we want to update.
   * @return The final moves to send to the server, or null if there are none.
   */
  public static List<MessageMove> getMoves(final Context context, final long accountId) {
    final ContentResolver cr = context.getContentResolver();
    final Cursor c = getCursor(cr, CONTENT_URI, ProjectionMoveQuery.PROJECTION, accountId);
    if (c == null) {
      return null;
    }

    // Collapse any rows in the cursor that are acting on the same message. We know the cursor
    // returned by getRowsToProcess is ordered from oldest to newest, and we use this fact to
    // get the original and final folder for the message.
    LongSparseArray<MessageMove> movesMap = new LongSparseArray();
    try {
      while (c.moveToNext()) {
        final long id = c.getLong(ProjectionMoveQuery.COLUMN_ID);
        final long messageKey = c.getLong(ProjectionMoveQuery.COLUMN_MESSAGE_KEY);
        final String serverId = c.getString(ProjectionMoveQuery.COLUMN_SERVER_ID);
        final long srcFolderKey = c.getLong(ProjectionMoveQuery.COLUMN_SRC_FOLDER_KEY);
        final long dstFolderKey = c.getLong(ProjectionMoveQuery.COLUMN_DST_FOLDER_KEY);
        final String srcFolderServerId =
            c.getString(ProjectionMoveQuery.COLUMN_SRC_FOLDER_SERVER_ID);
        final String dstFolderServerId =
            c.getString(ProjectionMoveQuery.COLUMN_DST_FOLDER_SERVER_ID);
        final MessageMove existingMove = movesMap.get(messageKey);
        if (existingMove != null) {
          if (existingMove.mLastId >= id) {
            LogUtils.w(LOG_TAG, "Moves were not in ascending id order");
          }
          if (!existingMove.mDstFolderServerId.equals(srcFolderServerId)
              || existingMove.mDstFolderKey != srcFolderKey) {
            LogUtils.w(LOG_TAG, "existing move's dst not same as this move's src");
          }
          existingMove.mDstFolderKey = dstFolderKey;
          existingMove.mDstFolderServerId = dstFolderServerId;
          existingMove.mLastId = id;
        } else {
          movesMap.put(
              messageKey,
              new MessageMove(
                  messageKey,
                  serverId,
                  id,
                  srcFolderKey,
                  dstFolderKey,
                  srcFolderServerId,
                  dstFolderServerId));
        }
      }
    } finally {
      c.close();
    }

    // Prune any no-op moves (i.e. messages that have been moved back to the initial folder).
    final int moveCount = movesMap.size();
    final long[] unmovedMessages = new long[moveCount];
    int unmovedMessagesCount = 0;
    final ArrayList<MessageMove> moves = new ArrayList(moveCount);
    for (int i = 0; i < movesMap.size(); ++i) {
      final MessageMove move = movesMap.valueAt(i);
      // We also treat changes without a server id as a no-op.
      if ((move.mServerId == null || move.mServerId.length() == 0)
          || move.mSrcFolderKey == move.mDstFolderKey) {
        unmovedMessages[unmovedMessagesCount] = move.mMessageKey;
        ++unmovedMessagesCount;
      } else {
        moves.add(move);
      }
    }
    if (unmovedMessagesCount != 0) {
      deleteRowsForMessages(cr, CONTENT_URI, unmovedMessages, unmovedMessagesCount);
    }
    if (moves.isEmpty()) {
      return null;
    }
    return moves;
  }
 /**
  * processStartupTask should be called when the very first ContentProvider is created is received
  * by this application
  *
  * @param context
  * @param broadcastIntext - the raw broadcast
  * @param cps - a list of ContentProvider Authorities to upgrade
  * @return
  */
 public static void processStartupTask(Context context) {
   LogUtils.i(LogUtils.TAG, "CPMaintenanceService - startup of first ContentProvider");
   Intent i = new Intent(context, CPMaintenanceService.class);
   i.setAction(ACTION_NORMAL_START);
   context.startService(i);
 }