ConfigUpdateInstallReceiver: pass content via content provider

When receiving a request to update ConfigUpdater content, don't
try to open by filename. Fetch the content via a file descriptor
delivered from a content provider. This avoids the files needing to
be marked world-readable, and resolves an SELinux violation.

Bug: 14989241
Change-Id: I10ad0d710c9a833a45995c545ba585a533c35b0d
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7db478d..1a3c66d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2893,36 +2893,42 @@
         <receiver android:name="com.android.server.updates.CertPinInstallReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_PINS" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
 
         <receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
 
         <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
 
         <receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
 
         <receiver android:name="com.android.server.updates.TZInfoInstallReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_TZINFO" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
 
         <receiver android:name="com.android.server.updates.SELinuxPolicyInstallReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_SEPOLICY" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
 
diff --git a/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java b/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
index 1a68fb3..7f7aae3 100644
--- a/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
@@ -20,6 +20,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.net.Uri;
 import android.provider.Settings;
 import android.util.Base64;
 import android.util.EventLog;
@@ -40,6 +41,7 @@
 import java.security.Signature;
 
 import libcore.io.IoUtils;
+import libcore.io.Streams;
 
 public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
 
@@ -73,7 +75,7 @@
                     // get the certificate from Settings.Secure
                     X509Certificate cert = getCert(context.getContentResolver());
                     // get the content path from the extras
-                    byte[] altContent = getAltContent(intent);
+                    byte[] altContent = getAltContent(context, intent);
                     // get the version from the extras
                     int altVersion = getVersionFromIntent(intent);
                     // get the previous value from the extras
@@ -127,12 +129,12 @@
         }
     }
 
-    private String getContentFromIntent(Intent i) {
-        String extraValue = i.getStringExtra(EXTRA_CONTENT_PATH);
-        if (extraValue == null) {
+    private Uri getContentFromIntent(Intent i) {
+        Uri data = i.getData();
+        if (data == null) {
             throw new IllegalStateException("Missing required content path, ignoring.");
         }
-        return extraValue;
+        return data;
     }
 
     private int getVersionFromIntent(Intent i) throws NumberFormatException {
@@ -169,8 +171,14 @@
         }
     }
 
-    private byte[] getAltContent(Intent i) throws IOException {
-        return IoUtils.readFileAsByteArray(getContentFromIntent(i));
+    private byte[] getAltContent(Context c, Intent i) throws IOException {
+        Uri content = getContentFromIntent(i);
+        InputStream is = c.getContentResolver().openInputStream(content);
+        try {
+            return Streams.readFullyNoClose(is);
+        } finally {
+            is.close();
+        }
     }
 
     private byte[] getCurrentContent() {