Merge "Materialize KeyChainActivity"
diff --git a/res/values-be-rBY/strings.xml b/res/values-be-rBY/strings.xml
index b63d5d0..263215f 100644
--- a/res/values-be-rBY/strings.xml
+++ b/res/values-be-rBY/strings.xml
@@ -19,10 +19,10 @@
     <string name="app_name" msgid="170210454004696382">"Ключавы ланцужок"</string>
     <string name="title_no_certs" msgid="8350009443064722873">"Сертыфiкаты не знойдзены"</string>
     <string name="title_select_cert" msgid="3588447616418041699">"Выберыце сертыфікат"</string>
-    <string name="requesting_application" msgid="1589142627467598421">"Прыкладанне %s запытала сертыфiкат. Выбар сертыфiката дазволiць прыкладанню выкарыстоўваць iдэнтыфiкатар для сервераў зараз i ў будучынi."</string>
-    <string name="requesting_server" msgid="5832565605998634370">"Прыкладанне вызначыла запытаны сервер як %s, але патрэбна адкрыць прыкладанню доступ да сертыфiката, калi вы яму давяраеце."</string>
-    <string name="install_new_cert_message" msgid="4451971501142085495">"Вы можаце ўсталяваць файл PKCS#12 з пашырэннем %1$s або %2$s, якiя знаходзяцца на знешнiм назапашвальнiку."</string>
+    <string name="requesting_application" msgid="1589142627467598421">"Праграма %s запытала сертыфiкат. Выбар сертыфiката дазволiць праграме выкарыстоўваць гэту ідэнтыфікацыю на серверах цяпер i ў будучынi."</string>
+    <string name="requesting_server" msgid="5832565605998634370">"Праграма ідэнтыфікавала запытаны сервер як %s, але, калi вы давяраеце праграме, вам трэба даць ёй доступ да сертыфiката."</string>
+    <string name="install_new_cert_message" msgid="4451971501142085495">"Сертыфікаты можна ўсталяваць з файла PKCS#12 з пашырэннем %1$s або %2$s, якi знаходзіцца на вонкавым сховішчы."</string>
     <string name="install_new_cert_button_label" msgid="510732745267546907">"Усталяваць"</string>
     <string name="allow_button" msgid="5340501035618157678">"Дазволіць"</string>
-    <string name="deny_button" msgid="3766539809121892584">"Забараніць"</string>
+    <string name="deny_button" msgid="3766539809121892584">"Адмовіць"</string>
 </resources>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index 5c59552..9a76fcd 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -19,7 +19,7 @@
     <string name="app_name" msgid="170210454004696382">"သော့တွဲ"</string>
     <string name="title_no_certs" msgid="8350009443064722873">"အသိအမှတ်ပြုလက်မှတ်မတွေ့ပါ"</string>
     <string name="title_select_cert" msgid="3588447616418041699">"အသိအမှတ်ပြုလက်မှတ် ရွေးချယ်ရန်"</string>
-    <string name="requesting_application" msgid="1589142627467598421">"အက်ပ် %s သည် အသိအမှတ်ပြုလက်မှတ် တောင်းခံနေပါသည်။ အသိအမှတ်ပြုလက်မှတ် ရွေးချယ်လိုက်ခြင်းအားဖြင့် ယခုနှင့် နောင်အနာဂတ်တွင် အက်ပ်ကို ဆာဗာများနှင့် ချိတ်ဆက်ရာတွင် အထောက်အထားဖြင့် သုံးစွဲနိုင်သည်။"</string>
+    <string name="requesting_application" msgid="1589142627467598421">"အက်ပ်%s သည် အသိအမှတ်ပြုလက်မှတ် တောင်းခံနေပါသည်။ အသိအမှတ်ပြုလက်မှတ် ရွေးချယ်လိုက်ခြင်းအားဖြင့် ယခုနှင့် နောင်အနာဂတ်တွင် အက်ပ်ကို ဆာဗာများနှင့် ချိတ်ဆက်ရာတွင် အထောက်အထားဖြင့် သုံးစွဲနိုင်သည်။"</string>
     <string name="requesting_server" msgid="5832565605998634370">"အပလီကေးရှင်းသည် တောင်းဆိုလာသောဆာဗာကို %sအနေဖြင့် ဖော်ပြသည်။ သို့သော် သင်သည် အပလီကေးရှင်းကို ယုံကြည်မှသာ သုံးစွဲရန် ခွင့်ပြုသင့်သည်။"</string>
     <string name="install_new_cert_message" msgid="4451971501142085495">"အသိအမှတ်ပြုလက်မှတ်များကို ပြင်ပ သိုလှောင်ရာများမှာရှိသော %1$s သို့မဟုတ် %2$s ဖိုင်နောက်ဆက်တွဲပါသော  PKCS#12 ဖိုင် များမှ ထည့်သွင်းနိုင်သည်။"</string>
     <string name="install_new_cert_button_label" msgid="510732745267546907">"ထည့်သွင်းရန်"</string>
diff --git a/src/com/android/keychain/KeyChainService.java b/src/com/android/keychain/KeyChainService.java
index 1d21fe5..8b3dcda 100644
--- a/src/com/android/keychain/KeyChainService.java
+++ b/src/com/android/keychain/KeyChainService.java
@@ -16,6 +16,7 @@
 
 package com.android.keychain;
 
+import android.app.BroadcastOptions;
 import android.app.IntentService;
 import android.content.ContentValues;
 import android.content.Context;
@@ -27,6 +28,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Binder;
+import android.os.Build;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.UserHandle;
@@ -151,7 +153,8 @@
             } catch (CertificateException e) {
                 throw new IllegalStateException(e);
             }
-            broadcastStorageChange();
+            broadcastLegacyStorageChange();
+            broadcastTrustStoreChange();
         }
 
         /**
@@ -198,7 +201,8 @@
                     return false;
                 }
             }
-            broadcastStorageChange();
+            broadcastKeychainChange();
+            broadcastLegacyStorageChange();
             return true;
         }
 
@@ -208,7 +212,8 @@
                 return false;
             }
             removeGrantsForAlias(alias);
-            broadcastStorageChange();
+            broadcastKeychainChange();
+            broadcastLegacyStorageChange();
             return true;
         }
 
@@ -232,7 +237,8 @@
                     }
                 }
             }
-            broadcastStorageChange();
+            broadcastTrustStoreChange();
+            broadcastLegacyStorageChange();
             return ok;
         }
 
@@ -243,7 +249,8 @@
             synchronized (mTrustedCertificateStore) {
                 ok = deleteCertificateEntry(alias);
             }
-            broadcastStorageChange();
+            broadcastTrustStoreChange();
+            broadcastLegacyStorageChange();
             return ok;
         }
 
@@ -289,7 +296,8 @@
         @Override public void setGrant(int uid, String alias, boolean value) {
             checkSystemCaller();
             setGrantInternal(mDatabaseHelper.getWritableDatabase(), uid, alias, value);
-            broadcastStorageChange();
+            broadcastPermissionChange(uid, alias, value);
+            broadcastLegacyStorageChange();
         }
 
         private ParceledListSlice<ParcelableString> makeAliasesParcelableSynchronised(
@@ -465,9 +473,37 @@
         }
     }
 
-    private void broadcastStorageChange() {
+    private void broadcastLegacyStorageChange() {
         Intent intent = new Intent(KeyChain.ACTION_STORAGE_CHANGED);
-        sendBroadcastAsUser(intent, new UserHandle(UserHandle.myUserId()));
+        BroadcastOptions opts = BroadcastOptions.makeBasic();
+        // TODO: Make this N-MR1 once N-MR1 API is available.
+        opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.N);
+        sendBroadcast(intent, null, opts.toBundle());
     }
 
+    private void broadcastKeychainChange() {
+        Intent intent = new Intent(KeyChain.ACTION_KEYCHAIN_CHANGED);
+        sendBroadcast(intent);
+    }
+
+    private void broadcastTrustStoreChange() {
+        Intent intent = new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED);
+        sendBroadcast(intent);
+    }
+
+    private void broadcastPermissionChange(int uid, String alias, boolean access) {
+        // Since the permission change only impacts one uid only send to that uid's packages.
+        final PackageManager packageManager = getPackageManager();
+        String[] packages = packageManager.getPackagesForUid(uid);
+        if (packages == null) {
+            return;
+        }
+        for (String pckg : packages) {
+            Intent intent = new Intent(KeyChain.ACTION_KEY_ACCESS_CHANGED);
+            intent.putExtra(KeyChain.EXTRA_KEY_ALIAS, alias);
+            intent.putExtra(KeyChain.EXTRA_KEY_ACCESSIBLE, access);
+            intent.setPackage(pckg);
+            sendBroadcast(intent);
+        }
+    }
 }