1baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee/* 2baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * Copyright (C) 2015 The Android Open Source Project 3baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * 4baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * Licensed under the Apache License, Version 2.0 (the "License"); 5baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * you may not use this file except in compliance with the License. 6baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * You may obtain a copy of the License at 7baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * 8baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * http://www.apache.org/licenses/LICENSE-2.0 9baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * 10baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * Unless required by applicable law or agreed to in writing, software 11baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * distributed under the License is distributed on an "AS IS" BASIS, 12baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * See the License for the specific language governing permissions and 14baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * limitations under the License. 15baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee */ 16baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 17baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leepackage com.android.settings; 18baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 19e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Leeimport android.annotation.LayoutRes; 20e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Leeimport android.annotation.Nullable; 21baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.app.AlertDialog; 2204046a1976a049a0450ab3be9b6725d440a4b122Robin Leeimport android.app.Dialog; 2304046a1976a049a0450ab3be9b6725d440a4b122Robin Leeimport android.app.DialogFragment; 2404046a1976a049a0450ab3be9b6725d440a4b122Robin Leeimport android.app.Fragment; 25baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.content.Context; 26baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.content.DialogInterface; 27baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.os.AsyncTask; 28baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.os.Bundle; 2904046a1976a049a0450ab3be9b6725d440a4b122Robin Leeimport android.os.Parcel; 3004046a1976a049a0450ab3be9b6725d440a4b122Robin Leeimport android.os.Parcelable; 31e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Leeimport android.os.Process; 32da7bc51615000469cda841637538476edbb7502fRobin Leeimport android.os.RemoteException; 33c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Leeimport android.os.UserHandle; 34c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Leeimport android.os.UserManager; 35baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.security.Credentials; 36da7bc51615000469cda841637538476edbb7502fRobin Leeimport android.security.IKeyChainService; 37da7bc51615000469cda841637538476edbb7502fRobin Leeimport android.security.KeyChain; 38da7bc51615000469cda841637538476edbb7502fRobin Leeimport android.security.KeyChain.KeyChainConnection; 39baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.security.KeyStore; 40ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Leeimport android.support.v7.widget.RecyclerView; 41da7bc51615000469cda841637538476edbb7502fRobin Leeimport android.util.Log; 42e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Leeimport android.util.SparseArray; 43baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.view.LayoutInflater; 44baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.view.View; 45baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.view.ViewGroup; 46baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport android.widget.TextView; 47baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 48265d3c2a0c36251bf8a9f571d7239b6dd404d942Tamas Berghammerimport com.android.internal.logging.nano.MetricsProto.MetricsEvent; 499579274cda38c552b43febe0980f0ec6bd07277dRicky Waiimport com.android.internal.widget.LockPatternUtils; 501e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhangimport com.android.settings.core.instrumentation.InstrumentedDialogFragment; 51ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Leeimport com.android.settings.SettingsPreferenceFragment; 52c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Leeimport com.android.settingslib.RestrictedLockUtils; 53c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Leeimport com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 54b70b3d86c96357c55e62386030cfe6634971ff7fRobin Lee 55e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Leeimport java.util.ArrayList; 56baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport java.util.EnumSet; 57e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Leeimport java.util.List; 58baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport java.util.SortedMap; 59baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport java.util.TreeMap; 60baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 61baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Leeimport static android.view.View.GONE; 6239b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport static android.view.View.VISIBLE; 63baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 64ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Leepublic class UserCredentialsSettings extends SettingsPreferenceFragment 65ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee implements View.OnClickListener { 66baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee private static final String TAG = "UserCredentialsSettings"; 67baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 68baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee @Override 696507613ebcd22e4691c2af92a5c161bd327db336Fan Zhang public int getMetricsCategory() { 70b70b3d86c96357c55e62386030cfe6634971ff7fRobin Lee return MetricsEvent.USER_CREDENTIALS; 71baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 72baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 73baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee @Override 74baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee public void onResume() { 75baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee super.onResume(); 7604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee refreshItems(); 77baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 78baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 79baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee @Override 80ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee public void onClick(final View view) { 81ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee final Credential item = (Credential) view.getTag(); 82ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee if (item != null) { 83ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee CredentialDialogFragment.show(this, item); 84ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee } 8504046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 8604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 8711fd5506ae9906b08cfa205914b21268cde91de6Robin Lee protected void announceRemoval(String alias) { 88ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee if (!isAdded()) { 89ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee return; 9011fd5506ae9906b08cfa205914b21268cde91de6Robin Lee } 91ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee getListView().announceForAccessibility(getString(R.string.user_credential_removed, alias)); 9211fd5506ae9906b08cfa205914b21268cde91de6Robin Lee } 9311fd5506ae9906b08cfa205914b21268cde91de6Robin Lee 9404046a1976a049a0450ab3be9b6725d440a4b122Robin Lee protected void refreshItems() { 9504046a1976a049a0450ab3be9b6725d440a4b122Robin Lee if (isAdded()) { 9604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee new AliasLoader().execute(); 9704046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 9804046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 9904046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 1001e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang public static class CredentialDialogFragment extends InstrumentedDialogFragment { 10104046a1976a049a0450ab3be9b6725d440a4b122Robin Lee private static final String TAG = "CredentialDialogFragment"; 10204046a1976a049a0450ab3be9b6725d440a4b122Robin Lee private static final String ARG_CREDENTIAL = "credential"; 10304046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 10404046a1976a049a0450ab3be9b6725d440a4b122Robin Lee public static void show(Fragment target, Credential item) { 10504046a1976a049a0450ab3be9b6725d440a4b122Robin Lee final Bundle args = new Bundle(); 10604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee args.putParcelable(ARG_CREDENTIAL, item); 10704046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 108f8e2dbf2d2590cdee3ff69f13b102b97620125f0Robin Lee if (target.getFragmentManager().findFragmentByTag(TAG) == null) { 109f8e2dbf2d2590cdee3ff69f13b102b97620125f0Robin Lee final DialogFragment frag = new CredentialDialogFragment(); 110f8e2dbf2d2590cdee3ff69f13b102b97620125f0Robin Lee frag.setTargetFragment(target, /* requestCode */ -1); 111f8e2dbf2d2590cdee3ff69f13b102b97620125f0Robin Lee frag.setArguments(args); 112f8e2dbf2d2590cdee3ff69f13b102b97620125f0Robin Lee frag.show(target.getFragmentManager(), TAG); 113f8e2dbf2d2590cdee3ff69f13b102b97620125f0Robin Lee } 11404046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 115baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 11604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee @Override 11704046a1976a049a0450ab3be9b6725d440a4b122Robin Lee public Dialog onCreateDialog(Bundle savedInstanceState) { 11804046a1976a049a0450ab3be9b6725d440a4b122Robin Lee final Credential item = (Credential) getArguments().getParcelable(ARG_CREDENTIAL); 119e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 12004046a1976a049a0450ab3be9b6725d440a4b122Robin Lee View root = getActivity().getLayoutInflater() 12104046a1976a049a0450ab3be9b6725d440a4b122Robin Lee .inflate(R.layout.user_credential_dialog, null); 12204046a1976a049a0450ab3be9b6725d440a4b122Robin Lee ViewGroup infoContainer = (ViewGroup) root.findViewById(R.id.credential_container); 123e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee View contentView = getCredentialView(item, R.layout.user_credential, null, 124e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee infoContainer, /* expanded */ true); 125e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee infoContainer.addView(contentView); 126c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee 127c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) 12804046a1976a049a0450ab3be9b6725d440a4b122Robin Lee .setView(root) 12904046a1976a049a0450ab3be9b6725d440a4b122Robin Lee .setTitle(R.string.user_credential_title) 130c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee .setPositiveButton(R.string.done, null); 131c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee 132c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee final String restriction = UserManager.DISALLOW_CONFIG_CREDENTIALS; 133c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee final int myUserId = UserHandle.myUserId(); 134c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee if (!RestrictedLockUtils.hasBaseUserRestriction(getContext(), restriction, myUserId)) { 135c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 136c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee @Override public void onClick(DialogInterface dialog, int id) { 137c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced( 138c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee getContext(), restriction, myUserId); 139c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee if (admin != null) { 140c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), 141c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee admin); 142c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee } else { 143e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee new RemoveCredentialsTask(getContext(), getTargetFragment()) 144e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee .execute(item); 145c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee } 146c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee dialog.dismiss(); 147c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee } 148c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee }; 149e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee if (item.isSystem()) { 150e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee // TODO: a safe means of clearing wifi certificates. Configs refer to aliases 151e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee // directly so deleting certs will break dependent access points. 152e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee builder.setNegativeButton(R.string.trusted_credentials_remove_label, listener); 153e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 154c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee } 155c421db78f0e49efdc7923b7df62743ac73ecfd0cRobin Lee return builder.create(); 15604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 15704046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 1581e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang @Override 1591e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang public int getMetricsCategory() { 1601e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang return MetricsEvent.DIALOG_USER_CREDENTIAL; 1611e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang } 1621e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang 163e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee /** 164e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * Deletes all certificates and keys under a given alias. 165e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * 166e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * If the {@link Credential} is for a system alias, all active grants to the alias will be 167e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * removed using {@link KeyChain}. 168e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee */ 169e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee private class RemoveCredentialsTask extends AsyncTask<Credential, Void, Credential[]> { 170e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee private Context context; 171da7bc51615000469cda841637538476edbb7502fRobin Lee private Fragment targetFragment; 172da7bc51615000469cda841637538476edbb7502fRobin Lee 173e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee public RemoveCredentialsTask(Context context, Fragment targetFragment) { 174e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee this.context = context; 175da7bc51615000469cda841637538476edbb7502fRobin Lee this.targetFragment = targetFragment; 176da7bc51615000469cda841637538476edbb7502fRobin Lee } 177da7bc51615000469cda841637538476edbb7502fRobin Lee 178da7bc51615000469cda841637538476edbb7502fRobin Lee @Override 179e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee protected Credential[] doInBackground(Credential... credentials) { 180e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee for (final Credential credential : credentials) { 181e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee if (credential.isSystem()) { 182e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee removeGrantsAndDelete(credential); 183e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee continue; 184da7bc51615000469cda841637538476edbb7502fRobin Lee } 185e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee throw new UnsupportedOperationException( 186e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee "Not implemented for wifi certificates. This should not be reachable."); 187e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 188e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee return credentials; 189e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 190e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 191e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee private void removeGrantsAndDelete(final Credential credential) { 192e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee final KeyChainConnection conn; 193e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee try { 194e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee conn = KeyChain.bind(getContext()); 195da7bc51615000469cda841637538476edbb7502fRobin Lee } catch (InterruptedException e) { 196e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee Log.w(TAG, "Connecting to KeyChain", e); 197e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee return; 198e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 199e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 200e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee try { 201e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee IKeyChainService keyChain = conn.getService(); 202e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee keyChain.removeKeyPair(credential.alias); 203e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } catch (RemoteException e) { 204e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee Log.w(TAG, "Removing credentials", e); 205e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } finally { 206e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee conn.close(); 207da7bc51615000469cda841637538476edbb7502fRobin Lee } 208da7bc51615000469cda841637538476edbb7502fRobin Lee } 209da7bc51615000469cda841637538476edbb7502fRobin Lee 210da7bc51615000469cda841637538476edbb7502fRobin Lee @Override 211e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee protected void onPostExecute(Credential... credentials) { 21211fd5506ae9906b08cfa205914b21268cde91de6Robin Lee if (targetFragment instanceof UserCredentialsSettings && targetFragment.isAdded()) { 21311fd5506ae9906b08cfa205914b21268cde91de6Robin Lee final UserCredentialsSettings target = (UserCredentialsSettings) targetFragment; 214e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee for (final Credential credential : credentials) { 215e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee target.announceRemoval(credential.alias); 21611fd5506ae9906b08cfa205914b21268cde91de6Robin Lee } 21711fd5506ae9906b08cfa205914b21268cde91de6Robin Lee target.refreshItems(); 218da7bc51615000469cda841637538476edbb7502fRobin Lee } 21904046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 22004046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 221baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 222baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 223baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee /** 224baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * Opens a background connection to KeyStore to list user credentials. 225baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * The credentials are stored in a {@link CredentialAdapter} attached to the main 226baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * {@link ListView} in the fragment. 227baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee */ 228e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee private class AliasLoader extends AsyncTask<Void, Void, List<Credential>> { 229e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee /** 230e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * @return a list of credentials ordered: 231e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * <ol> 232e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * <li>first by purpose;</li> 233e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * <li>then by alias.</li> 234e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * </ol> 235e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee */ 236baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee @Override 237e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee protected List<Credential> doInBackground(Void... params) { 238e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee final KeyStore keyStore = KeyStore.getInstance(); 239e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 240e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee // Certificates can be installed into SYSTEM_UID or WIFI_UID through CertInstaller. 241e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee final int myUserId = UserHandle.myUserId(); 242e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee final int systemUid = UserHandle.getUid(myUserId, Process.SYSTEM_UID); 243e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee final int wifiUid = UserHandle.getUid(myUserId, Process.WIFI_UID); 244e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 245e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee List<Credential> credentials = new ArrayList<>(); 246e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee credentials.addAll(getCredentialsForUid(keyStore, systemUid).values()); 247e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee credentials.addAll(getCredentialsForUid(keyStore, wifiUid).values()); 248e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee return credentials; 249e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 250e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 251e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee private SortedMap<String, Credential> getCredentialsForUid(KeyStore keyStore, int uid) { 252e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee final SortedMap<String, Credential> aliasMap = new TreeMap<>(); 253baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee for (final Credential.Type type : Credential.Type.values()) { 254e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee for (final String alias : keyStore.list(type.prefix, uid)) { 25552221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) { 25652221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu // Do not show work profile keys in user credentials 25752221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu if (alias.startsWith(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT) || 25852221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu alias.startsWith(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT)) { 25952221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu continue; 26052221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu } 26152221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu // Do not show synthetic password keys in user credential 26252221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu if (alias.startsWith(LockPatternUtils.SYNTHETIC_PASSWORD_KEY_PREFIX)) { 26352221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu continue; 26452221d80d20a3148f6b7d1e760f0ae00f0862180Rubin Xu } 2659579274cda38c552b43febe0980f0ec6bd07277dRicky Wai } 266e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee Credential c = aliasMap.get(alias); 267baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee if (c == null) { 268e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee c = new Credential(alias, uid); 269e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee aliasMap.put(alias, c); 270baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 271baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee c.storedTypes.add(type); 272baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 273baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 274e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee return aliasMap; 275baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 276baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 277baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee @Override 278e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee protected void onPostExecute(List<Credential> credentials) { 279ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee if (!isAdded()) { 280ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee return; 281ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee } 282ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee 283ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee if (credentials == null || credentials.size() == 0) { 284ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee // Create a "no credentials installed" message for the empty case. 285ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee TextView emptyTextView = (TextView) getActivity().findViewById(android.R.id.empty); 286ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee emptyTextView.setText(R.string.user_credential_none_installed); 287ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee setEmptyView(emptyTextView); 288ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee } else { 289ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee setEmptyView(null); 290ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee } 291ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee 292ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee getListView().setAdapter( 293ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee new CredentialAdapter(credentials, UserCredentialsSettings.this)); 294baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 295baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 296baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 297baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee /** 298baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * Helper class to display {@link Credential}s in a list. 299baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee */ 300ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee private static class CredentialAdapter extends RecyclerView.Adapter<ViewHolder> { 301e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee private static final int LAYOUT_RESOURCE = R.layout.user_credential_preference; 302e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 303ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee private final List<Credential> mItems; 304ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee private final View.OnClickListener mListener; 305ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee 306ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee public CredentialAdapter(List<Credential> items, @Nullable View.OnClickListener listener) { 307ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee mItems = items; 308ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee mListener = listener; 309ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee } 310ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee 311ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee @Override 312ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 313ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 314ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee return new ViewHolder(inflater.inflate(LAYOUT_RESOURCE, parent, false)); 315baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 316baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 317baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee @Override 318ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee public void onBindViewHolder(ViewHolder h, int position) { 319ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee getCredentialView(mItems.get(position), LAYOUT_RESOURCE, h.itemView, null, false); 320ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee h.itemView.setTag(mItems.get(position)); 321ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee h.itemView.setOnClickListener(mListener); 322ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee } 323ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee 324ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee @Override 325ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee public int getItemCount() { 326ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee return mItems.size(); 327ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee } 328ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee } 329ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee 330ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee private static class ViewHolder extends RecyclerView.ViewHolder { 331ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee public ViewHolder(View item) { 332ccaf9c91fc6765c202ae31c197d03eb064f23c6cRobin Lee super(item); 333e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 334e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 335e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 336e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee /** 337e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * Mapping from View IDs in {@link R} to the types of credentials they describe. 338e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee */ 339e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee private static final SparseArray<Credential.Type> credentialViewTypes = new SparseArray<>(); 340e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee static { 341e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee credentialViewTypes.put(R.id.contents_userkey, Credential.Type.USER_PRIVATE_KEY); 342e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee credentialViewTypes.put(R.id.contents_usercrt, Credential.Type.USER_CERTIFICATE); 343e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee credentialViewTypes.put(R.id.contents_cacrt, Credential.Type.CA_CERTIFICATE); 344e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 345e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 346e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee protected static View getCredentialView(Credential item, @LayoutRes int layoutResource, 347e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee @Nullable View view, ViewGroup parent, boolean expanded) { 348e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee if (view == null) { 349e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee view = LayoutInflater.from(parent.getContext()).inflate(layoutResource, parent, false); 350e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 351e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 352e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee ((TextView) view.findViewById(R.id.alias)).setText(item.alias); 353e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee ((TextView) view.findViewById(R.id.purpose)).setText(item.isSystem() 354e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee ? R.string.credential_for_vpn_and_apps 355e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee : R.string.credential_for_wifi); 356e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 357e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee view.findViewById(R.id.contents).setVisibility(expanded ? View.VISIBLE : View.GONE); 358e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee if (expanded) { 359e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee for (int i = 0; i < credentialViewTypes.size(); i++) { 360e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee final View detail = view.findViewById(credentialViewTypes.keyAt(i)); 361e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee detail.setVisibility(item.storedTypes.contains(credentialViewTypes.valueAt(i)) 362e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee ? View.VISIBLE : View.GONE); 363baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 364baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 365e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee return view; 366e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 367e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 368e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee static class AliasEntry { 369e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee public String alias; 370e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee public int uid; 371baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 372baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 373e26804208ce22e6118333c7f39f9d21adc1d702bRobin Lee static class Credential implements Parcelable { 374e26804208ce22e6118333c7f39f9d21adc1d702bRobin Lee static enum Type { 375baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee CA_CERTIFICATE (Credentials.CA_CERTIFICATE), 376baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee USER_CERTIFICATE (Credentials.USER_CERTIFICATE), 377baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee USER_PRIVATE_KEY (Credentials.USER_PRIVATE_KEY), 378baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee USER_SECRET_KEY (Credentials.USER_SECRET_KEY); 379baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 380baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee final String prefix; 381baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 382baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee Type(String prefix) { 383baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee this.prefix = prefix; 384baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 385baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 386baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 387baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee /** 388baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * Main part of the credential's alias. To fetch an item from KeyStore, prepend one of the 389baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * prefixes from {@link CredentialItem.storedTypes}. 390baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee */ 391baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee final String alias; 392baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 393baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee /** 394e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * UID under which this credential is stored. Typically {@link Process#SYSTEM_UID} but can 395e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee * also be {@link Process#WIFI_UID} for credentials installed as wifi certificates. 396e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee */ 397e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee final int uid; 398e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 399e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee /** 400baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * Should contain some non-empty subset of: 401baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * <ul> 402baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * <li>{@link Credentials.CA_CERTIFICATE}</li> 403baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * <li>{@link Credentials.USER_CERTIFICATE}</li> 404baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * <li>{@link Credentials.USER_PRIVATE_KEY}</li> 405baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * <li>{@link Credentials.USER_SECRET_KEY}</li> 406baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee * </ul> 407baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee */ 40804046a1976a049a0450ab3be9b6725d440a4b122Robin Lee final EnumSet<Type> storedTypes = EnumSet.noneOf(Type.class); 409baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee 410e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee Credential(final String alias, final int uid) { 411baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee this.alias = alias; 412e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee this.uid = uid; 413baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 41404046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 41504046a1976a049a0450ab3be9b6725d440a4b122Robin Lee Credential(Parcel in) { 416e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee this(in.readString(), in.readInt()); 41704046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 41804046a1976a049a0450ab3be9b6725d440a4b122Robin Lee long typeBits = in.readLong(); 41904046a1976a049a0450ab3be9b6725d440a4b122Robin Lee for (Type i : Type.values()) { 42004046a1976a049a0450ab3be9b6725d440a4b122Robin Lee if ((typeBits & (1L << i.ordinal())) != 0L) { 42104046a1976a049a0450ab3be9b6725d440a4b122Robin Lee storedTypes.add(i); 42204046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 42304046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 42404046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 42504046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 42604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee public void writeToParcel(Parcel out, int flags) { 42704046a1976a049a0450ab3be9b6725d440a4b122Robin Lee out.writeString(alias); 428e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee out.writeInt(uid); 42904046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 43004046a1976a049a0450ab3be9b6725d440a4b122Robin Lee long typeBits = 0; 43104046a1976a049a0450ab3be9b6725d440a4b122Robin Lee for (Type i : storedTypes) { 43204046a1976a049a0450ab3be9b6725d440a4b122Robin Lee typeBits |= 1L << i.ordinal(); 43304046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 43404046a1976a049a0450ab3be9b6725d440a4b122Robin Lee out.writeLong(typeBits); 43504046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 43604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 43704046a1976a049a0450ab3be9b6725d440a4b122Robin Lee public int describeContents() { 43804046a1976a049a0450ab3be9b6725d440a4b122Robin Lee return 0; 43904046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 44004046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 44104046a1976a049a0450ab3be9b6725d440a4b122Robin Lee public static final Parcelable.Creator<Credential> CREATOR 44204046a1976a049a0450ab3be9b6725d440a4b122Robin Lee = new Parcelable.Creator<Credential>() { 44304046a1976a049a0450ab3be9b6725d440a4b122Robin Lee public Credential createFromParcel(Parcel in) { 44404046a1976a049a0450ab3be9b6725d440a4b122Robin Lee return new Credential(in); 44504046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 44604046a1976a049a0450ab3be9b6725d440a4b122Robin Lee 44704046a1976a049a0450ab3be9b6725d440a4b122Robin Lee public Credential[] newArray(int size) { 44804046a1976a049a0450ab3be9b6725d440a4b122Robin Lee return new Credential[size]; 44904046a1976a049a0450ab3be9b6725d440a4b122Robin Lee } 45004046a1976a049a0450ab3be9b6725d440a4b122Robin Lee }; 451e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee 452e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee public boolean isSystem() { 453e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee return UserHandle.getAppId(uid) == Process.SYSTEM_UID; 454e68d9577772d312a4a8e7f47d6f2a74e0a5c2615Robin Lee } 455baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee } 456baefdcf9eb6f1ee9bf45b65b5e319be174e60735Robin Lee} 457