blob: 259c625e083ea4a70e211c50728dc0c871815fbd [file] [log] [blame]
/*
* Copyright (C) 2021 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.wifi;
import android.annotation.NonNull;
import android.net.wifi.IScoreUpdateObserver;
import android.net.wifi.WifiManager;
import android.util.Log;
import com.android.modules.utils.build.SdkLevel;
/**
* This is the callback proxy used to listen to external scorer actions triggered via
* {@link android.net.wifi.WifiManager.ScoreUpdateObserver}.
*
* <p>
* Note:
* <li>This was extracted out of {@link WifiScoreReport} class since that is not a singleton and
* is associated with a {@link ClientModeImpl} instance. However, this proxy sent to external scorer
* needs to be a singleton (i.e we cannot send the external scorer a new proxy every time
* a new primary {@link ClientModeImpl} is created).</li>
* <li> Whenever a new primary CMM is created, it needs to register to this proxy to listen for
* actions from the external scorer.</li>
* </p>
*/
public class ExternalScoreUpdateObserverProxy extends IScoreUpdateObserver.Stub {
private static final String TAG = "WifiExternalScoreUpdateObserverProxy";
private final WifiThreadRunner mWifiThreadRunner;
private WifiManager.ScoreUpdateObserver mCallback;
ExternalScoreUpdateObserverProxy(WifiThreadRunner wifiThreadRunner) {
mWifiThreadRunner = wifiThreadRunner;
}
/**
* Register a new callback to listen for events from external scorer.
*/
public void registerCallback(@NonNull WifiManager.ScoreUpdateObserver callback) {
if (mCallback != null) {
Log.i(TAG, "Replacing an existing callback (new primary CMM created)");
}
mCallback = callback;
}
/**
* Unregister callback to listen for events from external scorer.
*/
public void unregisterCallback(@NonNull WifiManager.ScoreUpdateObserver callback) {
// mCallback can be overwritten by another CMM, when we remove it we should only
// remove if it is the most recently registered mCallback
if (mCallback == callback) {
mCallback = null;
}
}
@Override
public void notifyScoreUpdate(int sessionId, int score) {
mWifiThreadRunner.post(() -> {
if (mCallback == null) {
Log.wtf(TAG, "No callback registered, dropping notifyScoreUpdate");
return;
}
mCallback.notifyScoreUpdate(sessionId, score);
});
}
@Override
public void triggerUpdateOfWifiUsabilityStats(int sessionId) {
mWifiThreadRunner.post(() -> {
if (mCallback == null) {
Log.wtf(TAG, "No callback registered, dropping triggerUpdateOfWifiUsability");
return;
}
mCallback.triggerUpdateOfWifiUsabilityStats(sessionId);
});
}
@Override
public void notifyStatusUpdate(int sessionId, boolean isUsable) {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
}
mWifiThreadRunner.post(() -> {
if (mCallback == null) {
Log.wtf(TAG, "No callback registered, dropping notifyStatusUpdate");
return;
}
mCallback.notifyStatusUpdate(sessionId, isUsable);
});
}
@Override
public void requestNudOperation(int sessionId) {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
}
mWifiThreadRunner.post(() -> {
if (mCallback == null) {
Log.wtf(TAG, "No callback registered, dropping requestNudOperation");
return;
}
mCallback.requestNudOperation(sessionId);
});
}
@Override
public void blocklistCurrentBssid(int sessionId) {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
}
mWifiThreadRunner.post(() -> {
if (mCallback == null) {
Log.wtf(TAG, "No callback registered, dropping requestNudOperation");
return;
}
mCallback.blocklistCurrentBssid(sessionId);
});
}
}