profcollect/betterbug integration with content uri
Test: manual
Bug: 183487233
Bug: 194155753
Change-Id: I6bdec2d090126c53d3cf2fa9deece2441eeafd98
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 54fb647..6c4fa96 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -641,6 +641,15 @@
</intent-filter>
</receiver>
+ <receiver
+ android:name=".ProfcollectUploadReceiver"
+ android:exported="true"
+ android:permission="android.permission.TRIGGER_SHELL_PROFCOLLECT_UPLOAD" >
+ <intent-filter>
+ <action android:name="com.android.shell.action.UPLOAD_REPORT" />
+ </intent-filter>
+ </receiver>
+
<service
android:name=".BugreportProgressService"
android:exported="false"/>
diff --git a/packages/Shell/res/xml/file_provider_paths.xml b/packages/Shell/res/xml/file_provider_paths.xml
index 225c757..85d7dd3 100644
--- a/packages/Shell/res/xml/file_provider_paths.xml
+++ b/packages/Shell/res/xml/file_provider_paths.xml
@@ -1,3 +1,4 @@
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="bugreports" path="bugreports/" />
+ <root-path name="profcollect" path="/data/misc/profcollectd/report/" />
</paths>
diff --git a/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java b/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java
new file mode 100644
index 0000000..d2da724
--- /dev/null
+++ b/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.shell;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.util.Log;
+
+import androidx.core.content.FileProvider;
+
+import com.android.internal.R;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * A proxy service that relays report upload requests to the uploader app, while translating
+ * the path to the report to a content URI owned by this service.
+ */
+public final class ProfcollectUploadReceiver extends BroadcastReceiver {
+ private static final String AUTHORITY = "com.android.shell";
+ private static final String PROFCOLLECT_DATA_ROOT = "/data/misc/profcollectd/report/";
+
+ private static final String LOG_TAG = "ProfcollectUploadReceiver";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(LOG_TAG, "Received upload intent");
+
+ String uploaderPkg = getUploaderPackageName(context);
+ String uploaderAction = getUploaderActionName(context);
+
+ try {
+ ApplicationInfo info = context.getPackageManager().getApplicationInfo(uploaderPkg,
+ 0);
+ if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ Log.e(LOG_TAG, "The profcollect uploader app " + uploaderPkg
+ + " must be a system application");
+ return;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(LOG_TAG, "Cannot find profcollect uploader app " + uploaderPkg);
+ return;
+ }
+
+ String filename = intent.getStringExtra("filename");
+ File reportFile = new File(PROFCOLLECT_DATA_ROOT + filename);
+ Uri reportUri = FileProvider.getUriForFile(context, AUTHORITY, reportFile);
+ Intent uploadIntent =
+ new Intent(uploaderAction)
+ .setPackage(uploaderPkg)
+ .putExtra("EXTRA_DESTINATION", "PROFCOLLECT")
+ .putExtra("EXTRA_PACKAGE_NAME", context.getPackageName())
+ .setData(reportUri)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+ List<ResolveInfo> receivers =
+ context.getPackageManager().queryBroadcastReceivers(uploadIntent, 0);
+ if (receivers == null || receivers.isEmpty()) {
+ Log.e(LOG_TAG, "No one to receive upload intent, abort upload.");
+ return;
+ }
+
+ context.grantUriPermission(uploaderPkg, reportUri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ context.sendBroadcast(uploadIntent);
+ }
+
+ private String getUploaderPackageName(Context context) {
+ return context.getResources().getString(
+ R.string.config_defaultProfcollectReportUploaderApp);
+ }
+
+ private String getUploaderActionName(Context context) {
+ return context.getResources().getString(
+ R.string.config_defaultProfcollectReportUploaderAction);
+ }
+}
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index fdf23d3..af65a2a 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -23,7 +23,6 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.IBinder.DeathRecipient;
import android.os.Looper;
@@ -32,8 +31,6 @@
import android.os.SystemProperties;
import android.os.UpdateEngine;
import android.os.UpdateEngineCallback;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.DeviceConfig;
import android.util.Log;
@@ -45,9 +42,6 @@
import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
import com.android.server.wm.ActivityTaskManagerInternal;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -306,79 +300,27 @@
return;
}
- if (!getUploaderEnabledConfig(getContext())) {
- return;
- }
-
+ Context context = getContext();
new Thread(() -> {
try {
- Context context = getContext();
- final String uploaderPkg = getUploaderPackageName(context);
- final String uploaderAction = getUploaderActionName(context);
- String reportUuid = mIProfcollect.report();
+ // Prepare profile report
+ String reportName = mIProfcollect.report() + ".zip";
- final int profileId = getBBProfileId();
- String reportDir = "/data/user/" + profileId
- + "/com.google.android.apps.internal.betterbug/cache/";
- String reportPath = reportDir + reportUuid + ".zip";
-
- if (!Files.exists(Paths.get(reportDir))) {
- Log.i(LOG_TAG, "Destination directory does not exist, abort upload.");
+ if (!context.getResources().getBoolean(
+ R.bool.config_profcollectReportUploaderEnabled)) {
+ Log.i(LOG_TAG, "Upload is not enabled.");
return;
}
- Intent uploadIntent =
- new Intent(uploaderAction)
- .setPackage(uploaderPkg)
- .putExtra("EXTRA_DESTINATION", "PROFCOLLECT")
- .putExtra("EXTRA_PACKAGE_NAME", getContext().getPackageName())
- .putExtra("EXTRA_PROFILE_PATH", reportPath)
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-
- List<ResolveInfo> receivers =
- context.getPackageManager().queryBroadcastReceivers(uploadIntent, 0);
- if (receivers == null || receivers.isEmpty()) {
- Log.i(LOG_TAG, "No one to receive upload intent, abort upload.");
- return;
- }
- mIProfcollect.copy_report_to_bb(profileId, reportUuid);
- context.sendBroadcast(uploadIntent);
- mIProfcollect.delete_report(reportUuid);
+ // Upload the report
+ Intent intent = new Intent()
+ .setPackage("com.android.shell")
+ .setAction("com.android.shell.action.UPLOAD_REPORT")
+ .putExtra("filename", reportName);
+ context.sendBroadcast(intent);
} catch (RemoteException e) {
Log.e(LOG_TAG, e.getMessage());
}
}).start();
}
-
- /**
- * Get BetterBug's profile ID. It is the work profile ID, if it exists. Otherwise the system
- * user ID.
- *
- * @return BetterBug's profile ID.
- */
- private int getBBProfileId() {
- UserManager userManager = UserManager.get(getContext());
- int[] profiles = userManager.getProfileIds(UserHandle.USER_SYSTEM, false);
- for (int p : profiles) {
- if (userManager.getUserInfo(p).isManagedProfile()) {
- return p;
- }
- }
- return UserHandle.USER_SYSTEM;
- }
-
- private boolean getUploaderEnabledConfig(Context context) {
- return context.getResources().getBoolean(
- R.bool.config_profcollectReportUploaderEnabled);
- }
-
- private String getUploaderPackageName(Context context) {
- return context.getResources().getString(
- R.string.config_defaultProfcollectReportUploaderApp);
- }
-
- private String getUploaderActionName(Context context) {
- return context.getResources().getString(
- R.string.config_defaultProfcollectReportUploaderAction);
- }
}