blob: 93e2d8d6fba400988a65d96d854ce4b2db666626 [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.Intent;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.android.internal.os.BackgroundThread;
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 implements
ActivityMetricsLaunchObserverRegistry, ActivityMetricsLaunchObserver {
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) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnIntentStarted, this, intent));
}
@Override
public void onIntentFailed() {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnIntentFailed, this));
}
@Override
public void onActivityLaunched(
@ActivityRecordProto byte[] activity,
int temperature) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnActivityLaunched,
this, activity, temperature));
}
@Override
public void onActivityLaunchCancelled(
@ActivityRecordProto byte[] activity) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnActivityLaunchCancelled, this, activity));
}
@Override
public void onActivityLaunchFinished(
@ActivityRecordProto byte[] activity) {
mHandler.sendMessage(PooledLambda.obtainMessage(
LaunchObserverRegistryImpl::handleOnActivityLaunchFinished, this, activity));
}
// 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) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
ActivityMetricsLaunchObserver o = mList.get(i);
o.onIntentStarted(intent);
}
}
private void handleOnIntentFailed() {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
ActivityMetricsLaunchObserver o = mList.get(i);
o.onIntentFailed();
}
}
private void handleOnActivityLaunched(
@ActivityRecordProto byte[] activity,
@Temperature int temperature) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
ActivityMetricsLaunchObserver o = mList.get(i);
o.onActivityLaunched(activity, temperature);
}
}
private void handleOnActivityLaunchCancelled(
@ActivityRecordProto byte[] activity) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
ActivityMetricsLaunchObserver o = mList.get(i);
o.onActivityLaunchCancelled(activity);
}
}
private void handleOnActivityLaunchFinished(
@ActivityRecordProto byte[] activity) {
// Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
for (int i = 0; i < mList.size(); i++) {
ActivityMetricsLaunchObserver o = mList.get(i);
o.onActivityLaunchFinished(activity);
}
}
}