Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e625806 authored by Yi Kong's avatar Yi Kong Committed by Automerger Merge Worker
Browse files

Merge "profcollect/betterbug integration with content uri" am: 0849b350 am: 282fa75f

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1784487

Change-Id: I97977f160adf82834d647650f8318c5c77eaa4d9
parents 026856ae 282fa75f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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"/>
+1 −0
Original line number Diff line number Diff line
<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>
+98 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}
+13 −71
Original line number Diff line number Diff line
@@ -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";
                // Prepare profile report
                String reportName = mIProfcollect.report() + ".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);
    }
}