diff options
4 files changed, 121 insertions, 71 deletions
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 54fb6475197a..6c4fa9684b1b 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 225c7571e7e2..85d7dd372294 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 000000000000..d2da724796cb --- /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 fdf23d3836ac..af65a2ad6a7d 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.app.job.JobService; 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.ServiceManager; 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.ActivityMetricsLaunchObserver; 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 @@ public final class ProfcollectForwardingService extends SystemService { 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(); - - 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."); - return; - } + // Prepare profile report + String reportName = mIProfcollect.report() + ".zip"; - 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."); + if (!context.getResources().getBoolean( + R.bool.config_profcollectReportUploaderEnabled)) { + Log.i(LOG_TAG, "Upload is not enabled."); 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); - } } |