From 2e4190fa43186b69e08d2fcc138cfd99686ae10a Mon Sep 17 00:00:00 2001 From: Alex Klyubin Date: Thu, 10 Oct 2013 11:33:00 -0700 Subject: Log APK hash for package install attempts in the Event Log. This CL adds a package_digest field to the install_package_attempt event. The field is populated with the SHA-256 digest of the contents of the APK iff the user has consented to app verification and app verification is enabled. Bug: 11275004 Bug: 10605940 (cherry picked from commit 8fca480bee00578c1529b1f32ab30af096db82dd) Change-Id: I9773925f7e397ada26efac022349dc8e4af01208 --- .../android/packageinstaller/EventLogTags.logtags | 2 +- .../packageinstaller/InstallAppProgress.java | 1 + .../packageinstaller/InstallFlowAnalytics.java | 124 +++++++++++++++++++-- .../packageinstaller/PackageInstallerActivity.java | 4 +- 4 files changed, 119 insertions(+), 12 deletions(-) diff --git a/src/com/android/packageinstaller/EventLogTags.logtags b/src/com/android/packageinstaller/EventLogTags.logtags index 01831488..8cbb1ccd 100644 --- a/src/com/android/packageinstaller/EventLogTags.logtags +++ b/src/com/android/packageinstaller/EventLogTags.logtags @@ -3,4 +3,4 @@ option java_package com.android.packageinstaller # APK install attempt via PackageInstaller (see InstallFlowAnalytics for format) -90300 install_package_attempt (result_and_flags|1),(total_time|1|3),(time_till_pkg_info_obtained|1|3),(time_till_install_clicked|1|3) +90300 install_package_attempt (result_and_flags|1),(total_time|1|3),(time_till_pkg_info_obtained|1|3),(time_till_install_clicked|1|3),(package_digest|3) diff --git a/src/com/android/packageinstaller/InstallAppProgress.java b/src/com/android/packageinstaller/InstallAppProgress.java index 83e4aa7f..c8e4133b 100755 --- a/src/com/android/packageinstaller/InstallAppProgress.java +++ b/src/com/android/packageinstaller/InstallAppProgress.java @@ -169,6 +169,7 @@ public class InstallAppProgress extends Activity implements View.OnClickListener Intent intent = getIntent(); mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO); mInstallFlowAnalytics = intent.getParcelableExtra(EXTRA_INSTALL_FLOW_ANALYTICS); + mInstallFlowAnalytics.setContext(this); mPackageURI = intent.getData(); final String scheme = mPackageURI.getScheme(); diff --git a/src/com/android/packageinstaller/InstallFlowAnalytics.java b/src/com/android/packageinstaller/InstallFlowAnalytics.java index ac8e53ac..2fc6db37 100644 --- a/src/com/android/packageinstaller/InstallFlowAnalytics.java +++ b/src/com/android/packageinstaller/InstallFlowAnalytics.java @@ -16,13 +16,27 @@ */ package com.android.packageinstaller; +import android.content.Context; import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.AsyncTask; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; +import android.provider.Settings; import android.util.EventLog; import android.util.Log; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import libcore.io.IoUtils; + /** * Analytics about an attempt to install a package via {@link PackageInstallerActivity}. * @@ -125,9 +139,14 @@ public class InstallFlowAnalytics implements Parcelable { */ private long mEndTimestampMillis; + /** URI of the package being installed. */ + private String mPackageUri; + /** Whether this attempt has been logged to the Event Log. */ private boolean mLogged; + private Context mContext; + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override @@ -151,6 +170,7 @@ public class InstallFlowAnalytics implements Parcelable { mPackageInfoObtainedTimestampMillis = in.readLong(); mInstallButtonClickTimestampMillis = in.readLong(); mEndTimestampMillis = in.readLong(); + mPackageUri = in.readString(); mLogged = readBoolean(in); } @@ -163,6 +183,7 @@ public class InstallFlowAnalytics implements Parcelable { dest.writeLong(mPackageInfoObtainedTimestampMillis); dest.writeLong(mInstallButtonClickTimestampMillis); dest.writeLong(mEndTimestampMillis); + dest.writeString(mPackageUri); writeBoolean(dest, mLogged); } @@ -179,6 +200,10 @@ public class InstallFlowAnalytics implements Parcelable { return 0; } + void setContext(Context context) { + mContext = context; + } + /** Sets whether the Unknown Sources setting is checked. */ void setInstallsFromUnknownSourcesPermitted(boolean permitted) { setFlagState(FLAG_INSTALLS_FROM_UNKNOWN_SOURCES_PERMITTED, permitted); @@ -229,6 +254,13 @@ public class InstallFlowAnalytics implements Parcelable { setFlagState(FLAG_FILE_URI, fileUri); } + /** + * Sets the URI of the package being installed. + */ + void setPackageUri(String packageUri) { + mPackageUri = packageUri; + } + /** * Gets whether an APK file is being installed. * @@ -393,33 +425,65 @@ public class InstallFlowAnalytics implements Parcelable { -mPackageManagerInstallResult); } - int resultAndFlags = (mResult & 0xff) + final int resultAndFlags = (mResult & 0xff) | ((packageManagerInstallResultByte & 0xff) << 8) | ((mFlags & 0xffff) << 16); // Total elapsed time from start to end, in milliseconds. - int totalElapsedTime = + final int totalElapsedTime = clipUnsignedLongToUnsignedInt(mEndTimestampMillis - mStartTimestampMillis); // Total elapsed time from start till information about the package being installed was // obtained, in milliseconds. - int elapsedTimeTillPackageInfoObtained = (isPackageInfoObtained()) + final int elapsedTimeTillPackageInfoObtained = (isPackageInfoObtained()) ? clipUnsignedLongToUnsignedInt( mPackageInfoObtainedTimestampMillis - mStartTimestampMillis) : 0; // Total elapsed time from start till Install button clicked, in milliseconds // milliseconds. - int elapsedTimeTillInstallButtonClick = (isInstallButtonClicked()) + final int elapsedTimeTillInstallButtonClick = (isInstallButtonClicked()) ? clipUnsignedLongToUnsignedInt( mInstallButtonClickTimestampMillis - mStartTimestampMillis) : 0; - EventLogTags.writeInstallPackageAttempt( - resultAndFlags, - totalElapsedTime, - elapsedTimeTillPackageInfoObtained, - elapsedTimeTillInstallButtonClick); + // If this user has consented to app verification, augment the logged event with the hash of + // the contents of the APK. + if (((mFlags & FLAG_FILE_URI) != 0) + && ((mFlags & FLAG_VERIFY_APPS_ENABLED) != 0) + && (isUserConsentToVerifyAppsGranted())) { + // Log the hash of the APK's contents. + // Reading the APK may take a while -- perform in background. + AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { + @Override + public void run() { + byte[] digest = null; + try { + digest = getPackageContentsDigest(); + } catch (IOException e) { + Log.w(TAG, "Failed to hash APK contents", e); + } finally { + String digestHex = (digest != null) + ? IntegralToString.bytesToHexString(digest, false) + : ""; + EventLogTags.writeInstallPackageAttempt( + resultAndFlags, + totalElapsedTime, + elapsedTimeTillPackageInfoObtained, + elapsedTimeTillInstallButtonClick, + digestHex); + } + } + }); + } else { + // Do not log the hash of the APK's contents + EventLogTags.writeInstallPackageAttempt( + resultAndFlags, + totalElapsedTime, + elapsedTimeTillPackageInfoObtained, + elapsedTimeTillInstallButtonClick, + ""); + } mLogged = true; if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -494,4 +558,46 @@ public class InstallFlowAnalytics implements Parcelable { private boolean isFlagSet(int flag) { return (mFlags & flag) == flag; } + + /** + * Checks whether the user has consented to app verification. + */ + private boolean isUserConsentToVerifyAppsGranted() { + return Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT, 0) != 0; + } + + /** + * Gets the digest of the contents of the package being installed. + */ + private byte[] getPackageContentsDigest() throws IOException { + File file = new File(Uri.parse(mPackageUri).getPath()); + return getSha256ContentsDigest(file); + } + + /** + * Gets the SHA-256 digest of the contents of the specified file. + */ + private static byte[] getSha256ContentsDigest(File file) throws IOException { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("SHA-256 not available", e); + } + + byte[] buf = new byte[8192]; + InputStream in = null; + try { + in = new BufferedInputStream(new FileInputStream(file), buf.length); + int chunkSize; + while ((chunkSize = in.read(buf)) != -1) { + digest.update(buf, 0, chunkSize); + } + } finally { + IoUtils.closeQuietly(in); + } + return digest.digest(); + } } \ No newline at end of file diff --git a/src/com/android/packageinstaller/PackageInstallerActivity.java b/src/com/android/packageinstaller/PackageInstallerActivity.java index a08e792d..a11e11eb 100644 --- a/src/com/android/packageinstaller/PackageInstallerActivity.java +++ b/src/com/android/packageinstaller/PackageInstallerActivity.java @@ -39,7 +39,6 @@ import android.os.Bundle; import android.os.SystemClock; import android.provider.Settings; import android.support.v4.view.ViewPager; -import android.util.EventLog; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -51,7 +50,6 @@ import android.widget.TabHost; import android.widget.TextView; import java.io.File; -import java.io.Serializable; import java.util.List; /* @@ -422,12 +420,14 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen boolean requestFromUnknownSource = isInstallRequestFromUnknownSource(intent); mInstallFlowAnalytics = new InstallFlowAnalytics(); + mInstallFlowAnalytics.setContext(this); mInstallFlowAnalytics.setStartTimestampMillis(SystemClock.elapsedRealtime()); mInstallFlowAnalytics.setInstallsFromUnknownSourcesPermitted( isInstallingUnknownAppsAllowed()); mInstallFlowAnalytics.setInstallRequestFromUnknownSource(requestFromUnknownSource); mInstallFlowAnalytics.setVerifyAppsEnabled(isVerifyAppsEnabled()); mInstallFlowAnalytics.setAppVerifierInstalled(isAppVerifierInstalled()); + mInstallFlowAnalytics.setPackageUri(mPackageURI.toString()); final String scheme = mPackageURI.getScheme(); if (scheme != null && !"file".equals(scheme) && !"package".equals(scheme)) { -- cgit v1.2.3 From ec930b14872fa68f1a1e5c8cb6bae08960fdc76b Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Mon, 28 Oct 2013 10:51:00 -0700 Subject: Import translations. DO NOT MERGE Change-Id: I304ee40cd39348cc847e6fd69a50300e612dfa51 Auto-generated-cl: translation import --- res/values-da/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 9d74a3b5..a43bcf0e 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -27,8 +27,8 @@ "Appen er installeret." "Vil du installere denne applikation? Den får adgang til:" "Vil du installere denne applikation? Den kræver ingen særlig adgang." - "Vil du installere en opdatering til den eksisterende applikation? Dine eksisterende data mistes ikke. Den opdaterede applikation får adgang til:" - "Vil du installere en opdatering til den indbyggede applikation? Dine eksisterende data mistes ikke. Den opdaterede applikation får adgang til:" + "Vil du installere en opdatering til den eksisterende app? Du mister ikke dine eksisterende data. Den opdaterede app kan gøre følgende:" + "Vil du installere en opdatering til den indbyggede app? Du mister ikke dine eksisterende data. Den opdaterede app kan gøre følgende:" "Vil du installere en opdatering til denne eksisterende applikation? Dine eksisterende data vil ikke gå tabt. Det kræver ikke nogen særlig adgang." "Vil du installere en opdatering til denne indbyggede applikation? Dine eksisterende data vil ikke gå tabt. Det kræver ikke nogen særlig adgang." "Appen blev ikke installeret." -- cgit v1.2.3 From e3e6b8b7ea7fd29c8fbf538fd6030e289cb7ca89 Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Mon, 4 Nov 2013 10:46:16 -0800 Subject: Import translations. DO NOT MERGE Change-Id: I020d2c5e2c66ea260e6c6ee665425124c3d579b0 Auto-generated-cl: translation import --- res/values-ar/strings.xml | 2 +- res/values-fa/strings.xml | 2 +- res/values-hi/strings.xml | 34 +++++++++++++++++----------------- res/values-iw/strings.xml | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index 6697f507..86dfbf5a 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -34,7 +34,7 @@ "التطبيق ليس مثبتًا." "يبدو أن الحزمة تالفة." "هناك حزمة حالية ذات توقيع متضارب، تم تثبيتها من قبل بالاسم نفسه." - "تعمل الحزمة فقط على إصدارات أحدث من Android." + "‏تعمل الحزمة فقط على إصدارات أحدث من Android." "هذا التطبيق ليس متوافقًا مع جهازك اللوحي." "لا يتوافق هذا التطبيق مع هاتفك." "تم حذف الحزمة المحددة قبل اكتمال عملية التثبيت." diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 5bd2e538..53fd7d89 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -34,7 +34,7 @@ "برنامه نصب نشد." "این بسته به نظر می‌رسد خراب است." "بسته فعلی با همین نام اما با امضای مختلف قبلاً نصب شده است." - "این بسته فقط در نسخه‌های جدیدتر Android کار می‌کند." + "‏این بسته فقط در نسخه‌های جدیدتر Android کار می‌کند." "این برنامه با رایانهٔ لوحی شما سازگار نیست." "این برنامه با تلفن شما سازگار نیست." "بسته مشخص شده قبل از تکمیل نصب حذف شده است." diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index db3b3642..ccffa030 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -20,23 +20,23 @@ "अगला" "इंस्‍टॉल करें" "पूर्ण" - "इस एप्स को यह करने दें:" + "इस ऐप्स को यह करने दें:" "रद्द करें" "अज्ञात" "इंस्‍टॉल कर रहा है…" - "एप्स इंस्‍टॉल हो गया." + "ऐप्स इंस्‍टॉल हो गया." "क्‍या आप इस ऐप्स को इंस्‍टॉल करना चाहते हैं? इससे यहां पर पहुंच प्राप्त होगी:" "क्‍या आप इस ऐप्स को इंस्‍टॉल करना चाहते हैं? इसके लिए किसी विशेष पहुंच की आवश्‍यकता नहीं है." "क्‍या आप इस मौजूदा एप के बारे में नई जानकारी इंस्‍टॉल करना चाहते हैं? आपका मौजूदा डेटा गुम नहीं होगा. नई जानकारी वाले एप से आपको इन पर पहुंच प्राप्त होगी:" "क्‍या आप इस अंतर्निहित एप के बारे में नई जानकारी इंस्‍टॉल करना चाहते हैं? आपका मौजूदा डेटा गुम नहीं होगा. नई जानकारी वाले ऐप्स से आपको इन पर पहुंच प्राप्त होगी:" - "क्या आप इस मौजूदा एप्स में नई जानकारी इंस्टॉल करना चाहते हैं? आपका मौजूदा डेटा बना रहेगा. इसे किसी विशेष पहुंच की आवश्यकता नहीं होती." + "क्या आप इस मौजूदा ऐप्स में नई जानकारी इंस्टॉल करना चाहते हैं? आपका मौजूदा डेटा बना रहेगा. इसे किसी विशेष पहुंच की आवश्यकता नहीं होती." "क्या आप इस अंतर्निहित एप में नई जानकारी इंस्टॉल करना चाहते हैं? आपका मौजूदा डेटा बना रहेगा. इसे किसी विशेष पहुंच की आवश्यकता नहीं होती." - "एप्स इंस्‍टॉल नहीं हुआ." + "ऐप्स इंस्‍टॉल नहीं हुआ." "पैकेज दूषित दिखाई देता है." "विरोधी हस्‍ताक्षर वाला समान नाम का एक मौजूदा पैकेज पहले से इंस्‍टॉल किया हुआ है." "पैकेज केवल Android के नवीनतम संस्‍करणों पर कार्य करता है." - "यह एप्स आपके टेबलेट के संगत नहीं है." - "यह एप्स आपके फ़ोन के संगत नहीं है." + "यह ऐप्स आपके टेबलेट के संगत नहीं है." + "यह ऐप्स आपके फ़ोन के संगत नहीं है." "नि‍र्दि‍ष्‍ट कि‍या गया पैकेज इंस्‍टॉल कि‍ए जाने से पहले ही हटा दि‍या गया था." "पैकेज ने सत्‍यापन पास नहीं कि‍या और इंस्‍टॉल नहीं कि‍या जा सका." "इस पैकेज को सत्‍यापित करते समय समयबाह्य हो गया. इसे बाद में पुन: इंस्‍टॉल करने का प्रयास करें." @@ -48,23 +48,23 @@ "सुरक्षा के लिए, आपका फ़ोन अज्ञात स्रोतों से मिले एप्‍लि. के इंस्‍टॉलेशन को अवरुद्ध करने हेतु सेट है." "ठीक है" "सेटिंग" - "एप्स के लिए नया स्रोत" + "ऐप्स के लिए नया स्रोत" "%1$s अन्‍य एप्‍लि‍केशन इंस्‍टॉल करना चाहता है.\n\nइसकी अनुमति‍ अभी दें या बाद में?" - "एप्स प्रबंधित करें" - "एप्स बदलें?" - "आप जिस एप्स को इंस्‍टॉल कर रहे हैं वह दूसरे एप्स को बदल देगा.\n\nआपका सभी पिछला उपयोगकर्ता डेटा सहेज लिया जाएगा." - "यह कोई सिस्‍टम एप्स है.\n\nआपका सभी पिछला उपयोगकर्ता डेटा सहेज लिया जाएगा." + "ऐप्स प्रबंधित करें" + "ऐप्स बदलें?" + "आप जिस ऐप्स को इंस्‍टॉल कर रहे हैं वह दूसरे ऐप्स को बदल देगा.\n\nआपका सभी पिछला उपयोगकर्ता डेटा सहेज लिया जाएगा." + "यह कोई सिस्‍टम ऐप्स है.\n\nआपका सभी पिछला उपयोगकर्ता डेटा सहेज लिया जाएगा." "स्थान नहीं है" "%1$s को इंस्‍टॉल नहीं किया जा सका. कुछ स्‍थान रिक्त करें और पुन: प्रयास करें." "ठीक है" - "एप्स नहीं मिला" - "एप्स, इंस्‍टॉल किए गए एप्स की सूची में नहीं मिला था." + "ऐप्स नहीं मिला" + "ऐप्स , इंस्‍टॉल किए गए ऐप्स की सूची में नहीं मिला था." "ऐप्स अनइंस्‍टॉल करें" "नई जानकारी अनइंस्‍टॉल करें" - "%1$s निम्‍न एप्स का भाग है:" - "क्‍या आप इस एप्स को अनइंस्‍टॉल करना चाहते हैं?" - "क्या आप इस एप्स को ""सभी"" उपयोगकर्ताओं के लिए अनइंस्टॉल करना चाहते हैं? एप्स और उसके डेटा को उपकरण पर ""सभी"" उपयोगकर्ताओं से निकाल दिया जाएगा." - "क्‍या आप इस एप्स को फ़ैक्‍टरी संस्‍करण से बदलना चाहते हैं?" + "%1$s निम्‍न ऐप्स का भाग है:" + "क्‍या आप इस ऐप्स को अनइंस्‍टॉल करना चाहते हैं?" + "क्या आप इस ऐप्स को ""सभी"" उपयोगकर्ताओं के लिए अनइंस्टॉल करना चाहते हैं? ऐप्स और उसके डेटा को उपकरण पर ""सभी"" उपयोगकर्ताओं से निकाल दिया जाएगा." + "क्‍या आप इस ऐप्स को फ़ैक्‍टरी संस्‍करण से बदलना चाहते हैं?" "अनइंस्‍टॉल कर रहा है…" "अनइंस्‍टॉल करना पूर्ण हो गया." "अनइंस्‍टॉल करना विफल." diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 0677005c..a89dfe8a 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -34,7 +34,7 @@ "האפליקציה לא הותקנה." "נראה שהחבילה פגומה." "כבר מותקנת חבילה קיימת באותו שם עם חתימה מתנגשת." - "החבילה פועלת רק בגרסאות חדשות יותר של Android." + "‏החבילה פועלת רק בגרסאות חדשות יותר של Android." "אפליקציה זו אינה תואמת לטאבלט שלך." "אפליקציה זו אינה תואמת לטלפון שלך." "החבילה שצוינה נמחקה לפני שההתקנה הושלמה." -- cgit v1.2.3