190 lines
6.5 KiB
Java
190 lines
6.5 KiB
Java
/*
|
|
* 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.internal.telephony;
|
|
|
|
import android.annotation.NonNull;
|
|
import android.os.AsyncResult;
|
|
import android.os.Handler;
|
|
import android.os.HandlerThread;
|
|
import android.os.Looper;
|
|
import android.os.Message;
|
|
import android.util.ArraySet;
|
|
import android.util.Log;
|
|
|
|
import com.android.internal.annotations.VisibleForTesting;
|
|
import com.android.telephony.Rlog;
|
|
|
|
import java.io.FileDescriptor;
|
|
import java.io.PrintWriter;
|
|
import java.util.Collections;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Provides the capabilities that the Radio Interface supports on the current device.
|
|
*/
|
|
public class RadioInterfaceCapabilityController extends Handler {
|
|
private static final String LOG_TAG =
|
|
RadioInterfaceCapabilityController.class.getSimpleName();
|
|
|
|
private static RadioInterfaceCapabilityController sInstance;
|
|
private final RadioConfig mRadioConfig;
|
|
private final CommandsInterface mCommandsInterface;
|
|
private Set<String> mRadioInterfaceCapabilities;
|
|
private final Object mLockRadioInterfaceCapabilities = new Object();
|
|
private static final int EVENT_GET_HAL_DEVICE_CAPABILITIES_DONE = 100;
|
|
|
|
/**
|
|
* Init method to instantiate the object
|
|
* Should only be called once.
|
|
*/
|
|
public static RadioInterfaceCapabilityController init(final RadioConfig radioConfig,
|
|
final CommandsInterface commandsInterface) {
|
|
synchronized (RadioInterfaceCapabilityController.class) {
|
|
if (sInstance == null) {
|
|
final HandlerThread handlerThread = new HandlerThread("RHC");
|
|
handlerThread.start();
|
|
sInstance = new RadioInterfaceCapabilityController(radioConfig, commandsInterface,
|
|
handlerThread.getLooper());
|
|
} else {
|
|
Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
|
|
}
|
|
return sInstance;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Static method to get instance.
|
|
*/
|
|
public static RadioInterfaceCapabilityController getInstance() {
|
|
if (sInstance == null) {
|
|
Log.wtf(LOG_TAG, "getInstance null");
|
|
}
|
|
|
|
return sInstance;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public RadioInterfaceCapabilityController(final RadioConfig radioConfig,
|
|
final CommandsInterface commandsInterface, final Looper looper) {
|
|
super(looper);
|
|
mRadioConfig = radioConfig;
|
|
mCommandsInterface = commandsInterface;
|
|
register();
|
|
}
|
|
|
|
private void requestCapabilities() {
|
|
if (mRadioInterfaceCapabilities != null) return;
|
|
|
|
mRadioConfig.getHalDeviceCapabilities(obtainMessage(
|
|
EVENT_GET_HAL_DEVICE_CAPABILITIES_DONE));
|
|
}
|
|
|
|
/**
|
|
* Gets the radio interface capabilities for the device
|
|
*/
|
|
@NonNull
|
|
public Set<String> getCapabilities() {
|
|
if (mRadioInterfaceCapabilities == null) {
|
|
// Only incur cost of synchronization block if mRadioInterfaceCapabilities isn't null
|
|
synchronized (mLockRadioInterfaceCapabilities) {
|
|
if (mRadioInterfaceCapabilities == null) {
|
|
requestCapabilities();
|
|
try {
|
|
if (Looper.myLooper() != getLooper()) {
|
|
mLockRadioInterfaceCapabilities.wait(2000);
|
|
}
|
|
} catch (final InterruptedException ignored) {
|
|
}
|
|
|
|
if (mRadioInterfaceCapabilities == null) {
|
|
loge("getRadioInterfaceCapabilities: Radio Capabilities not "
|
|
+ "loaded in time");
|
|
return new ArraySet<>();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return mRadioInterfaceCapabilities;
|
|
}
|
|
|
|
private void setupCapabilities(final @NonNull AsyncResult ar) {
|
|
if (mRadioInterfaceCapabilities == null) {
|
|
synchronized (mLockRadioInterfaceCapabilities) {
|
|
if (mRadioInterfaceCapabilities == null) {
|
|
if (ar.exception != null) {
|
|
loge("setupRadioInterfaceCapabilities: " + ar.exception);
|
|
}
|
|
if (ar.result == null) {
|
|
loge("setupRadioInterfaceCapabilities: ar.result is null");
|
|
return;
|
|
}
|
|
log("setupRadioInterfaceCapabilities: "
|
|
+ "mRadioInterfaceCapabilities now setup");
|
|
mRadioInterfaceCapabilities =
|
|
Collections.unmodifiableSet((Set<String>) ar.result);
|
|
if (mRadioInterfaceCapabilities != null) {
|
|
unregister();
|
|
}
|
|
}
|
|
mLockRadioInterfaceCapabilities.notify();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void register() {
|
|
// There is no radio HAL, capabilities are irrelevant in this case.
|
|
if (mCommandsInterface == null) {
|
|
mRadioInterfaceCapabilities = Collections.unmodifiableSet(new ArraySet<>());
|
|
return;
|
|
}
|
|
|
|
mCommandsInterface.registerForAvailable(this, Phone.EVENT_RADIO_AVAILABLE, null);
|
|
}
|
|
|
|
private void unregister() {
|
|
mCommandsInterface.unregisterForAvailable(this);
|
|
}
|
|
|
|
@Override
|
|
public void handleMessage(final Message msg) {
|
|
switch (msg.what) {
|
|
case Phone.EVENT_RADIO_AVAILABLE:
|
|
case Phone.EVENT_RADIO_ON:
|
|
requestCapabilities();
|
|
break;
|
|
case EVENT_GET_HAL_DEVICE_CAPABILITIES_DONE:
|
|
setupCapabilities((AsyncResult) msg.obj);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dump the fields of the instance
|
|
*/
|
|
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
|
pw.println("mRadioConfig=" + mRadioConfig);
|
|
}
|
|
|
|
private static void log(final String s) {
|
|
Rlog.d(LOG_TAG, s);
|
|
}
|
|
|
|
private static void loge(final String s) {
|
|
Rlog.e(LOG_TAG, s);
|
|
}
|
|
}
|