blob: 4eca577dcf4f515f38699dea17a0d11701d27c71 [file] [log] [blame]
/*
* 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.location.listeners;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import android.annotation.Nullable;
import android.location.util.identity.CallerIdentity;
import android.os.Process;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.FgThread;
import java.util.Objects;
import java.util.concurrent.Executor;
/**
* A listener registration representing a remote (possibly from a different process) listener.
* Listeners from a different process will be run on a direct executor, since the x-process listener
* invocation should already be asynchronous. Listeners from the same process will be run on a
* normal executor, since in-process listener invocation may be synchronous.
*
* @param <TRequest> request type
* @param <TListener> listener type
*/
public abstract class RemoteListenerRegistration<TRequest, TListener> extends
RemovableListenerRegistration<TRequest, TListener> {
@VisibleForTesting
public static final Executor IN_PROCESS_EXECUTOR = FgThread.getExecutor();
private static Executor chooseExecutor(CallerIdentity identity) {
// if a client is in the same process as us, binder calls will execute synchronously and
// we shouldn't run callbacks directly since they might be run under lock and deadlock
if (identity.getPid() == Process.myPid()) {
// there's a slight loophole here for pending intents - pending intent callbacks can
// always be run on the direct executor since they're always asynchronous, but honestly
// you shouldn't be using pending intent callbacks within the same process anyways
return IN_PROCESS_EXECUTOR;
} else {
return DIRECT_EXECUTOR;
}
}
private final CallerIdentity mIdentity;
protected RemoteListenerRegistration(@Nullable TRequest request, CallerIdentity identity,
TListener listener) {
super(chooseExecutor(identity), request, listener);
mIdentity = Objects.requireNonNull(identity);
}
/**
* Returns the listener identity.
*/
public final CallerIdentity getIdentity() {
return mIdentity;
}
}