Merge "Import translations. DO NOT MERGE" into klp-dev
diff --git a/res/mipmap-hdpi/ic_launcher_settings.png b/res/mipmap-hdpi/ic_launcher_settings.png
index 32da776..a8ccc89 100644
--- a/res/mipmap-hdpi/ic_launcher_settings.png
+++ b/res/mipmap-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_settings.png b/res/mipmap-mdpi/ic_launcher_settings.png
index 32a22ac..69709a8 100644
--- a/res/mipmap-mdpi/ic_launcher_settings.png
+++ b/res/mipmap-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_settings.png b/res/mipmap-xhdpi/ic_launcher_settings.png
index 9bfdd78..c3adce6 100644
--- a/res/mipmap-xhdpi/ic_launcher_settings.png
+++ b/res/mipmap-xhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_launcher_settings.png b/res/mipmap-xxhdpi/ic_launcher_settings.png
index 489ed6a..52fe978 100644
--- a/res/mipmap-xxhdpi/ic_launcher_settings.png
+++ b/res/mipmap-xxhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/mipmap-xxxhdpi/ic_launcher_settings.png b/res/mipmap-xxxhdpi/ic_launcher_settings.png
new file mode 100644
index 0000000..6b92795
--- /dev/null
+++ b/res/mipmap-xxxhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java
index 9173e39..fcf208a 100644
--- a/src/com/android/settings/CredentialStorage.java
+++ b/src/com/android/settings/CredentialStorage.java
@@ -25,6 +25,7 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
+import android.os.Process;
import android.security.Credentials;
import android.security.KeyChain.KeyChainConnection;
import android.security.KeyChain;
@@ -39,6 +40,14 @@
import android.widget.Toast;
import com.android.internal.widget.LockPatternUtils;
+import com.android.org.bouncycastle.asn1.ASN1InputStream;
+import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+
+import org.apache.harmony.security.utils.AlgNameMapper;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
/**
* CredentialStorage handles KeyStore reset, unlock, and install.
*
@@ -182,6 +191,20 @@
return (quality >= MIN_PASSWORD_QUALITY);
}
+ private boolean isHardwareBackedKey(byte[] keyData) {
+ try {
+ ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
+ PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
+ String algId = pki.getAlgorithmId().getAlgorithm().getId();
+ String algName = AlgNameMapper.map2AlgName(algId);
+
+ return KeyChain.isBoundKeyAlgorithm(algName);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to parse key data");
+ return false;
+ }
+ }
+
/**
* Install credentials if available, otherwise do nothing.
*/
@@ -196,17 +219,27 @@
String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
- if (!mKeyStore.importKey(key, value, uid, KeyStore.FLAG_ENCRYPTED)) {
+ int flags = KeyStore.FLAG_ENCRYPTED;
+ if (uid == Process.WIFI_UID && isHardwareBackedKey(value)) {
+ // Hardware backed keystore is secure enough to allow for WIFI stack
+ // to enable access to secure networks without user intervention
+ Log.d(TAG, "Saving private key with FLAG_NONE for WIFI_UID");
+ flags = KeyStore.FLAG_NONE;
+ }
+
+ if (!mKeyStore.importKey(key, value, uid, flags)) {
Log.e(TAG, "Failed to install " + key + " as user " + uid);
return;
}
}
+ int flags = (uid == Process.WIFI_UID) ? KeyStore.FLAG_NONE : KeyStore.FLAG_ENCRYPTED;
+
if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) {
String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME);
byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA);
- if (!mKeyStore.put(certName, certData, uid, KeyStore.FLAG_ENCRYPTED)) {
+ if (!mKeyStore.put(certName, certData, uid, flags)) {
Log.e(TAG, "Failed to install " + certName + " as user " + uid);
return;
}
@@ -216,7 +249,7 @@
String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME);
byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA);
- if (!mKeyStore.put(caListName, caListData, uid, KeyStore.FLAG_ENCRYPTED)) {
+ if (!mKeyStore.put(caListName, caListData, uid, flags)) {
Log.e(TAG, "Failed to install " + caListName + " as user " + uid);
return;
}
diff --git a/src/com/android/settings/deviceinfo/Memory.java b/src/com/android/settings/deviceinfo/Memory.java
index d03f6dc..999611d 100644
--- a/src/com/android/settings/deviceinfo/Memory.java
+++ b/src/com/android/settings/deviceinfo/Memory.java
@@ -19,6 +19,7 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -223,7 +224,11 @@
if (intent != null) {
// Don't go across app boundary if monkey is running
if (!Utils.isMonkeyRunning()) {
- startActivity(intent);
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException anfe) {
+ Log.w(TAG, "No activity found for intent " + intent);
+ }
}
return true;
}
diff --git a/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java b/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java
index 1992fac..4e5bd63 100644
--- a/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java
+++ b/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java
@@ -34,6 +34,7 @@
import android.os.storage.StorageVolume;
import android.preference.Preference;
import android.preference.PreferenceCategory;
+import android.provider.MediaStore;
import android.text.format.Formatter;
import com.android.settings.R;
@@ -437,8 +438,8 @@
} else if (pref == mItemDcim) {
intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- // TODO Create a Videos category, type = vnd.android.cursor.dir/video
- intent.setType("vnd.android.cursor.dir/image");
+ // TODO Create a Videos category, MediaStore.Video.Media.EXTERNAL_CONTENT_URI
+ intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
} else if (pref == mItemMisc) {
Context context = getContext().getApplicationContext();
intent = new Intent(context, MiscFilesHandler.class);
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
index c10f4b9..f739b4d 100644
--- a/src/com/android/settings/print/PrintServiceSettingsFragment.java
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -640,6 +640,11 @@
}
@Override
+ public boolean isEnabled(int position) {
+ return false;
+ }
+
+ @Override
public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
if (id == LOADER_ID_PRINTERS_LOADER) {
return new PrintersLoader(getActivity());
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index 96a7b47..f1022b9 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -347,6 +347,9 @@
protected Drawable getCircularUserIcon() {
Bitmap userIcon = mUserManager.getUserIcon(mUser.getIdentifier());
+ if (userIcon == null) {
+ return null;
+ }
CircleFramedDrawable circularIcon =
CircleFramedDrawable.getInstance(this.getActivity(), userIcon);
return circularIcon;
diff --git a/src/com/android/settings/users/RestrictedProfileSettings.java b/src/com/android/settings/users/RestrictedProfileSettings.java
index 1d712ac..c293536 100644
--- a/src/com/android/settings/users/RestrictedProfileSettings.java
+++ b/src/com/android/settings/users/RestrictedProfileSettings.java
@@ -37,6 +37,7 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.UserHandle;
import android.provider.MediaStore;
import android.provider.ContactsContract.DisplayPhoto;
import android.support.v4.content.FileProvider;
@@ -123,10 +124,25 @@
public void onResume() {
super.onResume();
- UserInfo info = mUserManager.getUserInfo(mUser.getIdentifier());
- ((TextView) mHeaderView.findViewById(android.R.id.title)).setText(info.name);
- ((ImageView) mHeaderView.findViewById(android.R.id.icon)).setImageDrawable(
- getCircularUserIcon());
+ // Check if user still exists
+ UserInfo info = getExistingUser(mUser);
+ if (info == null) {
+ finishFragment();
+ } else {
+ ((TextView) mHeaderView.findViewById(android.R.id.title)).setText(info.name);
+ ((ImageView) mHeaderView.findViewById(android.R.id.icon)).setImageDrawable(
+ getCircularUserIcon());
+ }
+ }
+
+ private UserInfo getExistingUser(UserHandle thisUser) {
+ final List<UserInfo> users = mUserManager.getUsers(true); // Only get non-dying
+ for (UserInfo user : users) {
+ if (user.id == thisUser.getIdentifier()) {
+ return user;
+ }
+ }
+ return null;
}
@Override