@Test
  public void testPromote() throws Exception {
    PromoteKeyOperation op =
        new PromoteKeyOperation(
            RuntimeEnvironment.application,
            new ProviderHelper(RuntimeEnvironment.application),
            null,
            null);

    PromoteKeyResult result =
        op.execute(new PromoteKeyringParcel(mStaticRing.getMasterKeyId(), null, null), null);

    Assert.assertTrue("promotion must succeed", result.success());

    {
      CachedPublicKeyRing ring =
          new ProviderHelper(RuntimeEnvironment.application)
              .getCachedPublicKeyRing(mStaticRing.getMasterKeyId());
      Assert.assertTrue("key must have a secret now", ring.hasAnySecret());

      Iterator<UncachedPublicKey> it = mStaticRing.getPublicKeys();
      while (it.hasNext()) {
        long keyId = it.next().getKeyId();
        Assert.assertEquals(
            "all subkeys must be gnu dummy", SecretKeyType.GNU_DUMMY, ring.getSecretKeyType(keyId));
      }
    }
  }
  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    mPubMasterKeyIds =
        getActivity().getIntent().getLongArrayExtra(CertifyKeyActivity.EXTRA_KEY_IDS);
    if (mPubMasterKeyIds == null) {
      Log.e(Constants.TAG, "List of key ids to certify missing!");
      getActivity().finish();
      return;
    }

    ArrayList<Boolean> checkedStates;
    if (savedInstanceState != null) {
      checkedStates = (ArrayList<Boolean>) savedInstanceState.getSerializable(ARG_CHECK_STATES);
      // key spinner and the checkbox keep their own state
    } else {
      checkedStates = null;

      // preselect certify key id if given
      long certifyKeyId =
          getActivity()
              .getIntent()
              .getLongExtra(CertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, Constants.key.none);
      if (certifyKeyId != Constants.key.none) {
        try {
          CachedPublicKeyRing key =
              (new ProviderHelper(getActivity())).getCachedPublicKeyRing(certifyKeyId);
          if (key.canCertify()) {
            mCertifyKeySpinner.setPreSelectedKeyId(certifyKeyId);
          }
        } catch (PgpKeyNotFoundException e) {
          Log.e(Constants.TAG, "certify certify check failed", e);
        }
      }
    }

    mUserIdsAdapter = new MultiUserIdsAdapter(getActivity(), null, 0, checkedStates);
    mUserIds.setAdapter(mUserIdsAdapter);
    mUserIds.setDividerHeight(0);

    getLoaderManager().initLoader(0, null, this);

    OperationResult result =
        getActivity().getIntent().getParcelableExtra(CertifyKeyActivity.EXTRA_RESULT);
    if (result != null) {
      // display result from import
      result.createNotify(getActivity()).show();
    }
  }
  /** Internal implementation to get cached passphrase. */
  private Passphrase getCachedPassphraseImpl(long masterKeyId, long subKeyId)
      throws ProviderHelper.NotFoundException {
    // on "none" key, just do nothing
    if (masterKeyId == Constants.key.none) {
      return null;
    }

    // passphrase for symmetric encryption?
    if (masterKeyId == Constants.key.symmetric) {
      Log.d(
          Constants.TAG,
          "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption");
      CachedPassphrase cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric);
      if (cachedPassphrase == null) {
        return null;
      }
      return cachedPassphrase.mPassphrase;
    }

    // try to get master key id which is used as an identifier for cached passphrases
    Log.d(
        Constants.TAG,
        "PassphraseCacheService.getCachedPassphraseImpl() for masterKeyId "
            + masterKeyId
            + ", subKeyId "
            + subKeyId);

    // get the type of key (from the database)
    CachedPublicKeyRing keyRing = new ProviderHelper(this).getCachedPublicKeyRing(masterKeyId);
    SecretKeyType keyType = keyRing.getSecretKeyType(subKeyId);

    switch (keyType) {
      case PASSPHRASE_EMPTY:
        return new Passphrase("");
      case UNAVAILABLE:
        throw new ProviderHelper.NotFoundException("secret key for this subkey is not available");
      case GNU_DUMMY:
        throw new ProviderHelper.NotFoundException(
            "secret key for stripped subkey is not available");
    }

    // get cached passphrase
    CachedPassphrase cachedPassphrase = mPassphraseCache.get(subKeyId);
    if (cachedPassphrase == null) {

      // If we cache strictly by subkey, exit early
      if (Preferences.getPreferences(mContext).getPassphraseCacheSubs()) {
        Log.d(
            Constants.TAG,
            "PassphraseCacheService: specific subkey passphrase not (yet) cached, returning null");
        // not really an error, just means the passphrase is not cached but not empty either
        return null;
      }

      if (subKeyId == masterKeyId) {
        Log.d(
            Constants.TAG,
            "PassphraseCacheService: masterkey passphrase not (yet) cached, returning null");
        // not really an error, just means the passphrase is not cached but not empty either
        return null;
      }

      cachedPassphrase = mPassphraseCache.get(masterKeyId);
      // If we cache strictly by subkey, exit early
      if (cachedPassphrase == null) {
        Log.d(
            Constants.TAG,
            "PassphraseCacheService: keyring passphrase not (yet) cached, returning null");
        // not really an error, just means the passphrase is not cached but not empty either
        return null;
      }
    }

    return cachedPassphrase.mPassphrase;
  }