Demo entry 6869379

Java

   

Submitted by anonymous on Aug 20, 2019 at 13:39
Language: Java. Code size: 4.9 kB.

// packageName即为待收集的目标应用包名
public int runSnapshotProfile(IPackageManager pm, String packageName, @UserIdInt int user) {
    if (TextUtils.isEmpty(packageName)) {
        Slog.wtf(TAG, "Invalid package!");
        return -1;
    }
    if (user < 0) {
        Slog.wtf(TAG, "Invalid user id: " + user);
        return -1;
    }
    if (pm == null) {
        Slog.wtf(TAG, "Error: PackageManager is not enabled");
    }
    final boolean isBootImage = "android".equals(packageName);
    String codePath = null;
    // If no code path was explicitly requested, select the base code path.
    String baseCodePath = null;

    try {
        if (!isBootImage) {
            PackageInfo packageInfo = pm.getPackageInfo(packageName, /* flags */ 0,
                    /* userId */user);
            if (packageInfo == null) {
                Slog.d(TAG, "Snapshot Profile: Package not found " + packageName);
                return -1;
            }
            baseCodePath = packageInfo.applicationInfo.getBaseCodePath();
            Slog.i(TAG, "runSnapshotProfile: package: " + packageName + " basecodePath: " + baseCodePath);
            if (codePath == null) {
                codePath = baseCodePath;
            }
        }
    } catch (RemoteException e) {
        Slog.e(TAG, "RemoteException getPackageInfo: ", e);
    }

    // Create the profile snapshot.
    final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback();
    // The calling package is needed to debug permission access.
    // callingPackage为调用该方法的应用包名,app层调用可改为自身package name
    final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID)
            ? "root" : "android";
    Slog.i(TAG, "runSnapshotProfile: callingPackage: " + callingPackage);
    final int profileType = isBootImage
            ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS;

    try {
        if (!pm.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) {
            Slog.w(TAG, "Error: Runtime profiling is not enabled :" + packageName);
            return -1;
        }
        pm.getArtManager().snapshotRuntimeProfile(profileType, packageName,
                codePath, callback, callingPackage);
    } catch (RemoteException e) {
        Slog.e(TAG, "RemoteException snapshotRuntimeProfile: ", e);
    }

    if (!callback.waitTillDone()) {
        Slog.e(TAG, "Error: Snapshot profile callback not called :"  + packageName);
        return callback.mErrCode;
    }

    // Copy the snapshot profile to the output profile file.
    // 写入备份目录
    try (InputStream inStream = new ParcelFileDescriptor.AutoCloseInputStream(callback.mProfileReadFd)) {
        File dirProfiles = new File(OPPO_PROFILE_SNAPSHOT_PATH);
        if (!dirProfiles.exists()) {
            Slog.e(TAG, "Error: directory not exist: " + OPPO_PROFILE_SNAPSHOT_PATH);
            return -1;
        }
        final String outputProfilePath = OPPO_PROFILE_SNAPSHOT_PATH + packageName 
                + PROFILE_FILE_EXTENSION; /*packageName.prof*/
        try (OutputStream outStream = new FileOutputStream(outputProfilePath)) {
            Streams.copy(inStream, outStream);
        }
        // Give read permissions to the other group.
        Os.chmod(outputProfilePath, /*mode*/ 0644 );
    } catch (IOException | ErrnoException e) {
        Slog.e(TAG,"Error when reading the profile fd: " + e.getMessage());
        return -1;
    }
    return 0;
}

private static class SnapshotRuntimeProfileCallback
        extends ISnapshotRuntimeProfileCallback.Stub {
    private boolean mSuccess = false;
    private int mErrCode = -1;
    private ParcelFileDescriptor mProfileReadFd = null;
    private CountDownLatch mDoneSignal = new CountDownLatch(1);

    @Override
    public void onSuccess(ParcelFileDescriptor profileReadFd) {
        mSuccess = true;
        try {
            // We need to dup the descriptor. We are in the same process as system server
            // and we will be receiving the same object (which will be closed on the
            // server side).
            mProfileReadFd = profileReadFd.dup();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mDoneSignal.countDown();
    }

    @Override
    public void onError(int errCode) {
        mSuccess = false;
        mErrCode = errCode;
        mDoneSignal.countDown();
    }

    boolean waitTillDone() {
        boolean done = false;
        try {
            // The time-out is an arbitrary large value. Since this is a local call 
            // the result will come very fast.
            done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException ignored) {
        }
        return done && mSuccess;
    }

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).