Loading src/com/android/packageinstaller/EventLogTags.logtags +1 −1 Original line number Diff line number Diff line Loading @@ -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) src/com/android/packageinstaller/InstallAppProgress.java +1 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading src/com/android/packageinstaller/InstallFlowAnalytics.java +115 −9 Original line number Diff line number Diff line Loading @@ -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}. * Loading Loading @@ -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<InstallFlowAnalytics> CREATOR = new Parcelable.Creator<InstallFlowAnalytics>() { @Override Loading @@ -151,6 +170,7 @@ public class InstallFlowAnalytics implements Parcelable { mPackageInfoObtainedTimestampMillis = in.readLong(); mInstallButtonClickTimestampMillis = in.readLong(); mEndTimestampMillis = in.readLong(); mPackageUri = in.readString(); mLogged = readBoolean(in); } Loading @@ -163,6 +183,7 @@ public class InstallFlowAnalytics implements Parcelable { dest.writeLong(mPackageInfoObtainedTimestampMillis); dest.writeLong(mInstallButtonClickTimestampMillis); dest.writeLong(mEndTimestampMillis); dest.writeString(mPackageUri); writeBoolean(dest, mLogged); } Loading @@ -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); Loading Loading @@ -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. * Loading Loading @@ -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; // 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); 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)) { Loading Loading @@ -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 src/com/android/packageinstaller/PackageInstallerActivity.java +2 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -51,7 +50,6 @@ import android.widget.TabHost; import android.widget.TextView; import java.io.File; import java.io.Serializable; import java.util.List; /* Loading Loading @@ -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)) { Loading Loading
src/com/android/packageinstaller/EventLogTags.logtags +1 −1 Original line number Diff line number Diff line Loading @@ -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)
src/com/android/packageinstaller/InstallAppProgress.java +1 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading
src/com/android/packageinstaller/InstallFlowAnalytics.java +115 −9 Original line number Diff line number Diff line Loading @@ -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}. * Loading Loading @@ -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<InstallFlowAnalytics> CREATOR = new Parcelable.Creator<InstallFlowAnalytics>() { @Override Loading @@ -151,6 +170,7 @@ public class InstallFlowAnalytics implements Parcelable { mPackageInfoObtainedTimestampMillis = in.readLong(); mInstallButtonClickTimestampMillis = in.readLong(); mEndTimestampMillis = in.readLong(); mPackageUri = in.readString(); mLogged = readBoolean(in); } Loading @@ -163,6 +183,7 @@ public class InstallFlowAnalytics implements Parcelable { dest.writeLong(mPackageInfoObtainedTimestampMillis); dest.writeLong(mInstallButtonClickTimestampMillis); dest.writeLong(mEndTimestampMillis); dest.writeString(mPackageUri); writeBoolean(dest, mLogged); } Loading @@ -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); Loading Loading @@ -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. * Loading Loading @@ -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; // 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); 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)) { Loading Loading @@ -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
src/com/android/packageinstaller/PackageInstallerActivity.java +2 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -51,7 +50,6 @@ import android.widget.TabHost; import android.widget.TextView; import java.io.File; import java.io.Serializable; import java.util.List; /* Loading Loading @@ -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)) { Loading