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

Commit 4914fdc6 authored by Yi Kong's avatar Yi Kong Committed by Automerger Merge Worker
Browse files

Introduce ProfcollectForwardingService am: a0bd2a99 am: fbeb0d80

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

Change-Id: I41b48dbf6a7c9272284b56ae1e1390c7d539e174
parents f22a7ac4 fbeb0d80
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@ filegroup {
        ":services.midi-sources",
        ":services.midi-sources",
        ":services.net-sources",
        ":services.net-sources",
        ":services.print-sources",
        ":services.print-sources",
        ":services.profcollect-sources",
        ":services.restrictions-sources",
        ":services.restrictions-sources",
        ":services.startop.iorap-sources",
        ":services.startop.iorap-sources",
        ":services.systemcaptions-sources",
        ":services.systemcaptions-sources",
@@ -73,6 +74,7 @@ java_library {
        "services.net",
        "services.net",
        "services.people",
        "services.people",
        "services.print",
        "services.print",
        "services.profcollect",
        "services.restrictions",
        "services.restrictions",
        "services.startop",
        "services.startop",
        "services.systemcaptions",
        "services.systemcaptions",
+7 −0
Original line number Original line Diff line number Diff line
@@ -152,6 +152,7 @@ import com.android.server.policy.role.LegacyRoleResolutionPolicy;
import com.android.server.power.PowerManagerService;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.power.ShutdownThread;
import com.android.server.power.ThermalManagerService;
import com.android.server.power.ThermalManagerService;
import com.android.server.profcollect.ProfcollectForwardingService;
import com.android.server.recoverysystem.RecoverySystemService;
import com.android.server.recoverysystem.RecoverySystemService;
import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.role.RoleManagerService;
import com.android.server.role.RoleManagerService;
@@ -1219,6 +1220,12 @@ public final class SystemServer {
            mSystemServiceManager.startService(IorapForwardingService.class);
            mSystemServiceManager.startService(IorapForwardingService.class);
            t.traceEnd();
            t.traceEnd();


            if (Build.IS_DEBUGGABLE) {
                t.traceBegin("ProfcollectForwardingService");
                mSystemServiceManager.startService(ProfcollectForwardingService.class);
                t.traceEnd();
            }

            t.traceBegin("SignedConfigService");
            t.traceBegin("SignedConfigService");
            SignedConfigService.registerUpdateReceiver(mSystemContext);
            SignedConfigService.registerUpdateReceiver(mSystemContext);
            t.traceEnd();
            t.traceEnd();
+35 −0
Original line number Original line Diff line number Diff line
// Copyright (C) 2020 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.

filegroup {
  name: "services.profcollect-javasources",
  srcs: ["src/**/*.java"],
  path: "src",
  visibility: ["//frameworks/base/services"],
}

filegroup {
  name: "services.profcollect-sources",
  srcs: [
    ":services.profcollect-javasources",
    ":profcollectd_aidl",
  ],
  visibility: ["//frameworks/base/services:__subpackages__"],
}

java_library_static {
  name: "services.profcollect",
  srcs: [":services.profcollect-sources"],
  libs: ["services.core"],
}
+3 −0
Original line number Original line Diff line number Diff line
srhines@google.com
yabinc@google.com
yikong@google.com
+196 −0
Original line number Original line Diff line number Diff line
/**
 * Copyright (C) 2020 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.server.profcollect;

import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder.DeathRecipient;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.Log;

import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.wm.ActivityMetricsLaunchObserver;
import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
import com.android.server.wm.ActivityTaskManagerInternal;

import java.util.concurrent.ThreadLocalRandom;

/**
 * System-server-local proxy into the {@code IProfcollectd} native service.
 */
public final class ProfcollectForwardingService extends SystemService {
    public static final String LOG_TAG = "ProfcollectForwardingService";

    private IProfCollectd mIProfcollect;
    private ProfcollectForwardingService mSelfService;
    private final Handler mHandler = new ProfcollectdHandler(IoThread.getHandler().getLooper());

    public ProfcollectForwardingService(Context context) {
        super(context);

        if (mSelfService != null) {
            throw new AssertionError("only one service instance allowed");
        }
        mSelfService = this;
    }

    @Override
    public void onStart() {
        Log.i(LOG_TAG, "Profcollect forwarding service start");
        connectNativeService();
        if (mIProfcollect == null) {
            return;
        }
        if (serviceHasSupportedTraceProvider()) {
            registerObservers();
        }
    }

    private boolean serviceHasSupportedTraceProvider() {
        if (mIProfcollect == null) {
            return false;
        }
        try {
            return !mIProfcollect.GetSupportedProvider().isEmpty();
        } catch (RemoteException e) {
            Log.e(LOG_TAG, e.getMessage());
            return false;
        }
    }

    private boolean tryConnectNativeService() {
        if (connectNativeService()) {
            return true;
        }
        // Cannot connect to the native service at this time, retry after a short delay.
        mHandler.sendEmptyMessageDelayed(ProfcollectdHandler.MESSAGE_BINDER_CONNECT, 5000);
        return false;
    }

    private boolean connectNativeService() {
        try {
            IProfCollectd profcollectd =
                    IProfCollectd.Stub.asInterface(
                            ServiceManager.getServiceOrThrow("profcollectd"));
            profcollectd.asBinder().linkToDeath(new ProfcollectdDeathRecipient(), /*flags*/0);
            mIProfcollect = profcollectd;
            return true;
        } catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
            Log.w(LOG_TAG, "Failed to connect profcollectd binder service.");
            return false;
        }
    }

    private class ProfcollectdHandler extends Handler {
        public ProfcollectdHandler(Looper looper) {
            super(looper);
        }

        public static final int MESSAGE_BINDER_CONNECT = 0;

        @Override
        public void handleMessage(android.os.Message message) {
            switch (message.what) {
                case MESSAGE_BINDER_CONNECT:
                    connectNativeService();
                    break;
                default:
                    throw new AssertionError("Unknown message: " + message.toString());
            }
        }
    }

    private class ProfcollectdDeathRecipient implements DeathRecipient {
        @Override
        public void binderDied() {
            Log.w(LOG_TAG, "profcollectd has died");

            mIProfcollect = null;
            tryConnectNativeService();
        }
    }

    // Event observers
    private void registerObservers() {
        registerAppLaunchObserver();
    }

    private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
    private void registerAppLaunchObserver() {
        ActivityTaskManagerInternal atmInternal =
                LocalServices.getService(ActivityTaskManagerInternal.class);
        ActivityMetricsLaunchObserverRegistry launchObserverRegistry =
                atmInternal.getLaunchObserverRegistry();
        launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver);
    }

    private void traceOnAppStart(String packageName) {
        if (mIProfcollect == null) {
            return;
        }

        // Sample for a fraction of app launches.
        int traceFrequency = SystemProperties.getInt("profcollectd.applaunch_trace_freq", 2);
        int randomNum = ThreadLocalRandom.current().nextInt(100);
        if (randomNum < traceFrequency) {
            try {
                Log.i(LOG_TAG, "Tracing on app launch event: " + packageName);
                mIProfcollect.TraceOnce("applaunch");
            } catch (RemoteException e) {
                Log.e(LOG_TAG, e.getMessage());
            }
        }
    }

    private class AppLaunchObserver implements ActivityMetricsLaunchObserver {
        @Override
        public void onIntentStarted(Intent intent, long timestampNanos) {
            traceOnAppStart(intent.getPackage());
        }

        @Override
        public void onIntentFailed() {
            // Ignored
        }

        @Override
        public void onActivityLaunched(byte[] activity, int temperature) {
            // Ignored
        }

        @Override
        public void onActivityLaunchCancelled(byte[] abortingActivity) {
            // Ignored
        }

        @Override
        public void onActivityLaunchFinished(byte[] finalActivity, long timestampNanos) {
            // Ignored
        }

        @Override
        public void onReportFullyDrawn(byte[] activity, long timestampNanos) {
            // Ignored
        }
    }
}