diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org')
14 files changed, 178 insertions, 50 deletions
| diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java index e796bdc91..40dcbd78d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014-2015 Vincent Breitmoser <v.breitmoser@mugenguild.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +  package org.sufficientlysecure.keychain.operations;  import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java index 65bc6381b..ebf0dc70b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014-2015 Vincent Breitmoser <v.breitmoser@mugenguild.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +  package org.sufficientlysecure.keychain.operations;  import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java index 124dd1aaf..5ef04ab05 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014-2015 Vincent Breitmoser <v.breitmoser@mugenguild.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +  package org.sufficientlysecure.keychain.operations;  import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index 7f14b08d9..bcd842dd0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014-2015 Vincent Breitmoser <v.breitmoser@mugenguild.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +  package org.sufficientlysecure.keychain.operations;  import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java index 783b32477..fd86d4b92 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014-2015 Vincent Breitmoser <v.breitmoser@mugenguild.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +  package org.sufficientlysecure.keychain.operations;  import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java index af60ea5ee..b5552a40d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014-2015 Vincent Breitmoser <v.breitmoser@mugenguild.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +  package org.sufficientlysecure.keychain.operations;  import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 5856589c4..6af5f4217 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -123,6 +123,7 @@ public class KeychainContract {          public static final String HAS_SIGN = "has_sign";          public static final String HAS_CERTIFY = "has_certify";          public static final String HAS_AUTHENTICATE = "has_authenticate"; +        public static final String HAS_DUPLICATE_USER_ID = "has_duplicate_user_id";          public static final String PUBKEY_DATA = "pubkey_data";          public static final String PRIVKEY_DATA = "privkey_data"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 4ccfc3cd9..1351e0cbc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -273,7 +273,15 @@ public class KeychainProvider extends ContentProvider {                  projectionMap.put(KeyRings.EXPIRY, Tables.KEYS + "." + Keys.EXPIRY);                  projectionMap.put(KeyRings.ALGORITHM, Tables.KEYS + "." + Keys.ALGORITHM);                  projectionMap.put(KeyRings.FINGERPRINT, Tables.KEYS + "." + Keys.FINGERPRINT); -                projectionMap.put(KeyRings.USER_ID, UserPackets.USER_ID); +                projectionMap.put(KeyRings.USER_ID, Tables.USER_PACKETS + "." + UserPackets.USER_ID); +                projectionMap.put(KeyRings.HAS_DUPLICATE_USER_ID, +                        "(SELECT COUNT (*) FROM " + Tables.USER_PACKETS + " AS dups" +                                + " WHERE dups." + UserPackets.MASTER_KEY_ID +                                    + " != " + Tables.KEYS + "." + Keys.MASTER_KEY_ID +                                + " AND dups." + UserPackets.RANK + " = 0" +                                + " AND dups." + UserPackets.USER_ID +                                    + " = "+ Tables.USER_PACKETS + "." + UserPackets.USER_ID +                                + ") AS " + KeyRings.HAS_DUPLICATE_USER_ID);                  projectionMap.put(KeyRings.VERIFIED, KeyRings.VERIFIED);                  projectionMap.put(KeyRings.PUBKEY_DATA,                          Tables.KEY_RINGS_PUBLIC + "." + KeyRingData.KEY_RING_DATA diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index b7f9bc99f..8c34efba2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -270,7 +270,8 @@ public class KeyListFragment extends LoaderFragment              KeyRings.IS_REVOKED,              KeyRings.IS_EXPIRED,              KeyRings.VERIFIED, -            KeyRings.HAS_ANY_SECRET +            KeyRings.HAS_ANY_SECRET, +            KeyRings.HAS_DUPLICATE_USER_ID,      };      static final int INDEX_MASTER_KEY_ID = 1; @@ -279,6 +280,7 @@ public class KeyListFragment extends LoaderFragment      static final int INDEX_IS_EXPIRED = 4;      static final int INDEX_VERIFIED = 5;      static final int INDEX_HAS_ANY_SECRET = 6; +    static final int INDEX_HAS_DUPLICATE_USER_ID = 7;      static final String ORDER =              KeyRings.HAS_ANY_SECRET + " DESC, UPPER(" + KeyRings.USER_ID + ") ASC"; @@ -707,6 +709,7 @@ public class KeyListFragment extends LoaderFragment                  boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;                  boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;                  boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; +                boolean hasDuplicate = cursor.getInt(INDEX_HAS_DUPLICATE_USER_ID) == 1;                  h.mMasterKeyId = masterKeyId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java index 18f1ef8a7..c3a8d60f8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -135,7 +135,9 @@ public class ViewKeyFragment extends LoaderFragment implements          if (mIsSecret) {//all secret keys are linked to "me" profile in contacts              contactId = ContactHelper.getMainProfileContactId(resolver);              List<String> mainProfileNames = ContactHelper.getMainProfileContactName(context); -            if (mainProfileNames != null) contactName = mainProfileNames.get(0); +            if (mainProfileNames != null && mainProfileNames.size() > 0) { +                contactName = mainProfileNames.get(0); +            }          } else {              contactId = ContactHelper.findContactId(resolver, masterKeyId); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index fc912fccb..53d1eb7e7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -68,7 +68,9 @@ public class CertifyKeySpinner extends KeySpinner {                  KeychainContract.KeyRings.IS_REVOKED,                  KeychainContract.KeyRings.IS_EXPIRED,                  KeychainContract.KeyRings.HAS_CERTIFY, -                KeychainContract.KeyRings.HAS_ANY_SECRET +                KeychainContract.KeyRings.HAS_ANY_SECRET, +                KeychainContract.KeyRings.HAS_DUPLICATE_USER_ID, +                KeychainContract.KeyRings.CREATION          };          String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1 AND " diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index c8eceea50..ab5b02301 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -25,6 +25,7 @@ import android.support.v4.app.LoaderManager;  import android.support.v4.content.Loader;  import android.support.v4.widget.CursorAdapter;  import android.support.v7.internal.widget.TintSpinner; +import android.text.format.DateFormat;  import android.util.AttributeSet;  import android.view.View;  import android.view.ViewGroup; @@ -41,6 +42,10 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;  import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;  import org.sufficientlysecure.keychain.util.Log; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +  /**   * Use TintSpinner from AppCompat lib instead of Spinner. Fixes white dropdown icon.   * Related: http://stackoverflow.com/a/27713090 @@ -139,11 +144,12 @@ public abstract class KeySpinner extends TintSpinner implements LoaderManager.Lo      protected class SelectKeyAdapter extends BaseAdapter implements SpinnerAdapter {          private CursorAdapter inner;          private int mIndexUserId; -        private int mIndexKeyId; +        private int mIndexDuplicate;          private int mIndexMasterKeyId; +        private int mIndexCreationDate;          public SelectKeyAdapter() { -            inner = new CursorAdapter(null, null, 0) { +            inner = new CursorAdapter(getContext(), null, 0) {                  @Override                  public View newView(Context context, Cursor cursor, ViewGroup parent) {                      return View.inflate(getContext(), R.layout.keyspinner_item, null); @@ -154,12 +160,26 @@ public abstract class KeySpinner extends TintSpinner implements LoaderManager.Lo                      TextView vKeyName = (TextView) view.findViewById(R.id.keyspinner_key_name);                      ImageView vKeyStatus = (ImageView) view.findViewById(R.id.keyspinner_key_status);                      TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); -                    TextView vKeyId = (TextView) view.findViewById(R.id.keyspinner_key_id); +                    TextView vDuplicate = (TextView) view.findViewById(R.id.keyspinner_duplicate);                      String[] userId = KeyRing.splitUserId(cursor.getString(mIndexUserId));                      vKeyName.setText(userId[2] == null ? userId[0] : (userId[0] + " (" + userId[2] + ")"));                      vKeyEmail.setText(userId[1]); -                    vKeyId.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix(getContext(), cursor.getLong(mIndexKeyId))); + +                    boolean duplicate = cursor.getLong(mIndexDuplicate) > 0; +                    if (duplicate) { +                        Date creationDate = new Date(cursor.getLong(mIndexCreationDate) * 1000); +                        Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); +                        creationCal.setTime(creationDate); +                        // convert from UTC to time zone of device +                        creationCal.setTimeZone(TimeZone.getDefault()); + +                        vDuplicate.setText(context.getString(R.string.label_creation) + ": " +                                + DateFormat.getDateFormat(context).format(creationCal.getTime())); +                        vDuplicate.setVisibility(View.VISIBLE); +                    } else { +                        vDuplicate.setVisibility(View.GONE); +                    }                      boolean valid = setStatus(getContext(), cursor, vKeyStatus);                      setItemEnabled(view, valid); @@ -181,18 +201,18 @@ public abstract class KeySpinner extends TintSpinner implements LoaderManager.Lo              TextView vKeyName = (TextView) view.findViewById(R.id.keyspinner_key_name);              ImageView vKeyStatus = (ImageView) view.findViewById(R.id.keyspinner_key_status);              TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); -            TextView vKeyId = (TextView) view.findViewById(R.id.keyspinner_key_id); +            TextView vKeyDuplicate = (TextView) view.findViewById(R.id.keyspinner_duplicate);              if (enabled) {                  vKeyName.setTextColor(Color.BLACK);                  vKeyEmail.setTextColor(Color.BLACK); -                vKeyId.setTextColor(Color.BLACK); +                vKeyDuplicate.setTextColor(Color.BLACK);                  vKeyStatus.setVisibility(View.GONE);                  view.setClickable(false);              } else {                  vKeyName.setTextColor(Color.GRAY);                  vKeyEmail.setTextColor(Color.GRAY); -                vKeyId.setTextColor(Color.GRAY); +                vKeyDuplicate.setTextColor(Color.GRAY);                  vKeyStatus.setVisibility(View.VISIBLE);                  // this is a HACK. the trick is, if the element itself is clickable, the                  // click is not passed on to the view list @@ -203,9 +223,10 @@ public abstract class KeySpinner extends TintSpinner implements LoaderManager.Lo          public Cursor swapCursor(Cursor newCursor) {              if (newCursor == null) return inner.swapCursor(null); -            mIndexKeyId = newCursor.getColumnIndex(KeychainContract.KeyRings.KEY_ID); +            mIndexDuplicate = newCursor.getColumnIndex(KeychainContract.KeyRings.HAS_DUPLICATE_USER_ID);              mIndexUserId = newCursor.getColumnIndex(KeychainContract.KeyRings.USER_ID);              mIndexMasterKeyId = newCursor.getColumnIndex(KeychainContract.KeyRings.MASTER_KEY_ID); +            mIndexCreationDate = newCursor.getColumnIndex(KeychainContract.KeyRings.CREATION);              if (newCursor.moveToFirst()) {                  do {                      if (newCursor.getLong(mIndexMasterKeyId) == mSelectedKeyId) { @@ -257,19 +278,17 @@ public abstract class KeySpinner extends TintSpinner implements LoaderManager.Lo                  TextView vKeyName = (TextView) view.findViewById(R.id.keyspinner_key_name);                  ImageView vKeyStatus = (ImageView) view.findViewById(R.id.keyspinner_key_status);                  TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); -                TextView vKeyId = (TextView) view.findViewById(R.id.keyspinner_key_id); +                TextView vKeyDuplicate = (TextView) view.findViewById(R.id.keyspinner_duplicate);                  vKeyName.setText(R.string.choice_none);                  vKeyEmail.setVisibility(View.GONE); -                vKeyId.setVisibility(View.GONE); +                vKeyDuplicate.setVisibility(View.GONE);                  vKeyStatus.setVisibility(View.GONE);                  setItemEnabled(view, true);              } else {                  view = inner.getView(position - 1, convertView, parent);                  TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); -                TextView vKeyId = (TextView) view.findViewById(R.id.keyspinner_key_id);                  vKeyEmail.setVisibility(View.VISIBLE); -                vKeyId.setVisibility(View.VISIBLE);              }              return view;          } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java index 10327a6a4..df7347fa4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java @@ -59,7 +59,9 @@ public class SignKeySpinner extends KeySpinner {                  KeychainContract.KeyRings.IS_REVOKED,                  KeychainContract.KeyRings.IS_EXPIRED,                  KeychainContract.KeyRings.HAS_SIGN, -                KeychainContract.KeyRings.HAS_ANY_SECRET +                KeychainContract.KeyRings.HAS_ANY_SECRET, +                KeychainContract.KeyRings.HAS_DUPLICATE_USER_ID, +                KeychainContract.KeyRings.CREATION          };          String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java index c07d7a36b..6efc0a5ea 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java @@ -222,18 +222,20 @@ public class ContactHelper {       * @return       */      public static long getMainProfileContactId(ContentResolver resolver) { -        Cursor profileCursor = resolver.query( -                ContactsContract.Profile.CONTENT_URI, -                new String[]{ -                        ContactsContract.Profile._ID -                }, -                null, null, null); -        if (profileCursor == null) { +        Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI, +                new String[]{ ContactsContract.Profile._ID}, null, null, null); + +        if(profileCursor != null && profileCursor.getCount() != 0 && profileCursor.moveToNext()) { +            long contactId = profileCursor.getLong(0); +            profileCursor.close(); +            return contactId; +        } +        else { +            if(profileCursor != null) { +                profileCursor.close(); +            }              return -1;          } - -        profileCursor.moveToNext(); -        return profileCursor.getLong(0);      }      /** @@ -426,25 +428,14 @@ public class ContactHelper {       */      public static void writeKeysToContacts(Context context) {          ContentResolver resolver = context.getContentResolver(); -        Set<Long> deletedKeys = getRawContactMasterKeyIds(resolver); - -        writeKeysToMainProfileContact(context);          if (Constants.DEBUG_SYNC_REMOVE_CONTACTS) {              debugDeleteRawContacts(resolver);          } -//        ContentProviderClient client = resolver.acquireContentProviderClient(ContactsContract.AUTHORITY_URI); -//        ContentValues values = new ContentValues(); -//        Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE); -//        values.put(ContactsContract.Settings.ACCOUNT_NAME, account.name); -//        values.put(ContactsContract.Settings.ACCOUNT_TYPE, account.type); -//        values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, true); -//        try { -//            client.insert(ContactsContract.Settings.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build(), values); -//        } catch (RemoteException e) { -//            e.printStackTrace(); -//        } +        writeKeysToMainProfileContact(context, resolver); + +        Set<Long> deletedKeys = getRawContactMasterKeyIds(resolver);          // Load all public Keys from OK          // TODO: figure out why using selectionArgs does not work in this case @@ -457,7 +448,6 @@ public class ContactHelper {              while (cursor.moveToNext()) {                  long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);                  String[] userIdSplit = KeyRing.splitUserId(cursor.getString(INDEX_USER_ID)); -                String keyIdShort = KeyFormattingUtils.convertKeyIdToHexShort(cursor.getLong(INDEX_MASTER_KEY_ID));                  boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;                  boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;                  boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; @@ -487,7 +477,7 @@ public class ContactHelper {                          Log.d(Constants.TAG, "Insert new raw contact with masterKeyId " + masterKeyId);                          insertContact(ops, context, masterKeyId); -                        writeContactKey(ops, context, rawContactId, masterKeyId, keyIdShort); +                        writeContactKey(ops, context, rawContactId, masterKeyId, userIdSplit[0]);                      }                      // We always update the display name (which is derived from primary user id) @@ -517,8 +507,7 @@ public class ContactHelper {       *       * @param context       */ -    public static void writeKeysToMainProfileContact(Context context) { -        ContentResolver resolver = context.getContentResolver(); +    public static void writeKeysToMainProfileContact(Context context, ContentResolver resolver) {          Set<Long> keysToDelete = getMainProfileMasterKeyIds(resolver);          // get all keys which have associated secret keys @@ -532,20 +521,20 @@ public class ContactHelper {                  long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);                  boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;                  boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; +                String[] userIdSplit = KeyRing.splitUserId(cursor.getString(INDEX_USER_ID)); -                if (!isExpired && !isRevoked) { +                if (!isExpired && !isRevoked && userIdSplit[0] != null) {                      // if expired or revoked will not be removed from keysToDelete or inserted                      // into main profile ("me" contact)                      boolean existsInMainProfile = keysToDelete.remove(masterKeyId);                      if (!existsInMainProfile) {                          long rawContactId = -1;//new raw contact -                        String keyIdShort = KeyFormattingUtils.convertKeyIdToHexShort(masterKeyId);                          Log.d(Constants.TAG, "masterKeyId with secret " + masterKeyId);                          ArrayList<ContentProviderOperation> ops = new ArrayList<>();                          insertMainProfileRawContact(ops, masterKeyId); -                        writeContactKey(ops, context, rawContactId, masterKeyId, keyIdShort); +                        writeContactKey(ops, context, rawContactId, masterKeyId, userIdSplit[0]);                          try {                              resolver.applyBatch(ContactsContract.AUTHORITY, ops); @@ -763,10 +752,10 @@ public class ContactHelper {       * This creates the link to OK in contact details       */      private static void writeContactKey(ArrayList<ContentProviderOperation> ops, Context context, long rawContactId, -                                        long masterKeyId, String keyIdShort) { +                                        long masterKeyId, String keyName) {          ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), rawContactId)                  .withValue(ContactsContract.Data.MIMETYPE, Constants.CUSTOM_CONTACT_DATA_MIME_TYPE) -                .withValue(ContactsContract.Data.DATA1, context.getString(R.string.contact_show_key, keyIdShort)) +                .withValue(ContactsContract.Data.DATA1, context.getString(R.string.contact_show_key, keyName))                  .withValue(ContactsContract.Data.DATA2, masterKeyId)                  .build());      } | 
