blob: 9cbc1bdcbeebdce11b1aea61034a82036b30cef6 [file] [log] [blame]
/*
* Copyright (C) 2018 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.wm;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import com.android.internal.util.function.pooled.PooledLambda;
import java.util.ArrayList;
/**
* Multi-cast implementation of {@link ActivityMetricsLaunchObserver}.
*
* <br /><br />
* If this class is called through the {@link ActivityMetricsLaunchObserver} interface,
* then the call is forwarded to all registered observers at the time.
*
* <br /><br />
* All calls are invoked asynchronously in-order on a background thread. This fulfills the
* sequential ordering guarantee in {@link ActivityMetricsLaunchObserverRegistry}.
*
* @see ActivityTaskManagerInternal#getLaunchObserverRegistry()
*/
class LaunchObserverRegistryImpl extends ActivityMetricsLaunchObserver implements
ActivityMetricsLaunchObserverRegistry {
private final ArrayList<ActivityMetricsLaunchObserver> mList = new ArrayList<>();
/**
* All calls are posted to a handler because:
*
* 1. We don't know how long the observer will take to handle this call and we don't want
* to block the WM critical section on it.
* 2. We don't know the lock ordering of the observer so we don't want to expose a chance
* of deadlock.
*/
private final Handler mHandler;
public LaunchObserverRegistryImpl(Looper looper) {
mHandler = new Handler(looper);
}
@Override
public void registerLaunchObserver(ActivityMetricsLaunchObserver launchObserver) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleRegisterLaunchObserver, this, launchObserver));
}
@Override
public void unregisterLaunchObserver(ActivityMetricsLaunchObserver launchObserver) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleUnregisterLaunchObserver, this, launchObserver));
}
@Override
public void onIntentStarted(Intent intent, long timestampNs) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnIntentStarted,
this,
intent,
timestampNs));
}
@Override
public void onIntentFailed(long id) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnIntentFailed, this, id));
}
@Override
public void onActivityLaunched(long id, ComponentName name, int temperature) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnActivityLaunched,
this, id, name, temperature));
}
@Override
public void onActivityLaunchCancelled(long id) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnActivityLaunchCancelled, this, id));
}
@Override
public void onActivityLaunchFinished(long id, ComponentName name, long timestampNs) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnActivityLaunchFinished,
this, id, name, timestampNs));
}
@Override
public void onReportFullyDrawn(long id, long timestampNs) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnReportFullyDrawn,
this, id, timestampNs));
}
// Use PooledLambda.obtainMessage to invoke below methods. Every method reference must be
// unbound (i.e. not capture any variables explicitly or implicitly) to fulfill the
// singleton-lambda requirement.
private void handleRegisterLaunchObserver(ActivityMetricsLaunchObserver observer) {
mList.add(observer);
}
private void handleUnregisterLaunchObserver(ActivityMetricsLaunchObserver observer) {
mList.remove(observer);
}
private void handleOnIntentStarted(Intent intent, long timestampNs) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
mList.get(i).onIntentStarted(intent, timestampNs);
}
}
private void handleOnIntentFailed(long id) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
mList.get(i).onIntentFailed(id);
}
}
private void handleOnActivityLaunched(long id, ComponentName name,
@Temperature int temperature) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
mList.get(i).onActivityLaunched(id, name, temperature);
}
}
private void handleOnActivityLaunchCancelled(long id) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
mList.get(i).onActivityLaunchCancelled(id);
}
}
private void handleOnActivityLaunchFinished(long id, ComponentName name, long timestampNs) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
mList.get(i).onActivityLaunchFinished(id, name, timestampNs);
}
}
private void handleOnReportFullyDrawn(long id, long timestampNs) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
mList.get(i).onReportFullyDrawn(id, timestampNs);
}
}
}