Fix TrustedCredentialsSettings NPE

[Cause of Defect]
TrustedCredentialsSettings#mKeyChainConnectionByProfileId is get/set by
more than one thread. Main thread would set it in onDestroy method, and
AsyncTask would get and set in the doInBackground method. So
mKeyChainConnectionByProfileId.get(profileId) would get null after
onDestroy method get called.

Bug: N/A
Test: Debugger to simulate concurrency
Change-Id: I0664d1e9b88b079855354ce0e6fe014a98a22327
Signed-off-by: daqi <daqi@xiaomi.com>
This commit is contained in:
daqi
2017-09-05 09:53:05 +08:00
parent 0bed3cacd7
commit be47df7395

View File

@@ -61,6 +61,7 @@ import android.widget.Switch;
import android.widget.TabHost;
import android.widget.TextView;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.UnlaunchableAppActivity;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
@@ -152,6 +153,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment
private int mConfirmingCredentialUser;
private IntConsumer mConfirmingCredentialListener;
private Set<AdapterData.AliasLoader> mAliasLoaders = new ArraySet<AdapterData.AliasLoader>(2);
@GuardedBy("mKeyChainConnectionByProfileId")
private final SparseArray<KeyChainConnection>
mKeyChainConnectionByProfileId = new SparseArray<KeyChainConnection>();
@@ -256,12 +258,14 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment
}
private void closeKeyChainConnections() {
synchronized (mKeyChainConnectionByProfileId) {
final int n = mKeyChainConnectionByProfileId.size();
for (int i = 0; i < n; ++i) {
mKeyChainConnectionByProfileId.valueAt(i).close();
}
mKeyChainConnectionByProfileId.clear();
}
}
private void addTab(Tab tab) {
TabHost.TabSpec systemSpec = mTabHost.newTabSpec(tab.mTag)
@@ -684,6 +688,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment
SparseArray<List<CertHolder>> certHoldersByProfile =
new SparseArray<List<CertHolder>>();
try {
synchronized(mKeyChainConnectionByProfileId) {
List<UserHandle> profiles = mUserManager.getUserProfiles();
final int n = profiles.size();
// First we get all aliases for all profiles in order to show progress
@@ -740,6 +745,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment
certHoldersByProfile.put(profileId, certHolders);
}
return certHoldersByProfile;
}
} catch (RemoteException e) {
Log.e(TAG, "Remote exception while loading aliases.", e);
return new SparseArray<List<CertHolder>>();
@@ -936,6 +942,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment
public List<X509Certificate> getX509CertsFromCertHolder(CertHolder certHolder) {
List<X509Certificate> certificates = null;
try {
synchronized (mKeyChainConnectionByProfileId) {
KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
certHolder.mProfileId);
IKeyChainService service = keyChainConnection.getService();
@@ -947,6 +954,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment
X509Certificate certificate = KeyChain.toCertificate(encodedCertificate);
certificates.add(certificate);
}
}
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException while retrieving certificate chain for root "
+ certHolder.mAlias, ex);
@@ -985,6 +993,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment
@Override
protected Boolean doInBackground(Void... params) {
try {
synchronized (mKeyChainConnectionByProfileId) {
KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
mCertHolder.mProfileId);
IKeyChainService service = keyChainConnection.getService();
@@ -995,6 +1004,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment
} else {
return service.deleteCaCertificate(mCertHolder.mAlias);
}
}
} catch (CertificateEncodingException | SecurityException | IllegalStateException
| RemoteException e) {
Log.w(TAG, "Error while toggling alias " + mCertHolder.mAlias, e);