Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c935977b authored by Nitin Shivpure's avatar Nitin Shivpure
Browse files

Bt: Add support for interop conf feature

Snapshot of:
558ee40545537cac75f561c6b35c21ec388218a5
3e76e1c8460e566e37eb2e6fa2116804d967e4e7
5229383750c1278c7bd3d940d59c5c50a18a1053
5752baca5abdfa5f30e803a67827f119fbe03339
4a63a13ebe0b8576a30fe1d5efc1b6d99ebab28f
2a7911429a78d33de0570335fac08ef9469a3621
73c5720caabd944c11906192298c858e2e586885
2c3b5e9ac41b4bbb946387334e7e0b0a4c32c65e
d907b0cf64f1eecdd87b96c09980d89ccf9fc897
a7d8799123a10cfc5a32bc8aafdd938166f912db
dbd88bfc3f8a63c8df24571205413a1170e947e2
319d2310997dd53f835e1729aa513bef6839c32e
7489832bbf0482ac19bd67d9446f8b0323c850d9
deb8aa88ab3df0f11981311beb50281c0cef1f43
050e9ea9d75d5a576aedff7e0a155b5b98a582ae
9a080f23406f101f76956b8226a5956e0e875062
d1a2484905c10821dfb5dfa7bd5579e5ff5f307e
f726e3467f570f8c28d9ea9d5f8c4040445e7791
272d58799f73c044aadc9daf74991e39e7b93bff
c67929e52961254985b93835e0834de2c0be40a8
2e43f9bb24046c88fc443f801d4e8ad5fe048a58
5c48da0d4631157f7cd6541363758c6d83b36691
01922f885641365887b4f1900355ef35cb816d2e
3dfd8a30897ea1c5d4b4548be820a96cbfb79f3d
ae79a1e066e9ae7c7359c5f2a19a6fb0485a2217
a85581f04f0d97d769405d400f4a0aa44f17e3a2
a1234fd3d1063c8cc31da64be1ac373112c4d987
c778c918e8249693d0bc5f483299396a83dc19e3
9419b00e227ec087eb6c79d33a6be3d2e25b32b9
502ddc2b9d115eaf46e113569d0720bb977d058b

Test: atest net_test_device
Bug: 252903680

Merged-In: I959ee79fe74d0b22a26b3df1633ee88670d396d1
Change-Id: I959ee79fe74d0b22a26b3df1633ee88670d396d1
parent 209a7561
Loading
Loading
Loading
Loading
+193 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016-2017 The Linux Foundation
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
@@ -1854,6 +1855,186 @@ static jboolean isLogRedactionEnabled(JNIEnv* env, jobject obj) {
  return bluetooth::os::should_log_be_redacted();
}

static jboolean interopMatchAddrNative(JNIEnv* env, jclass clazz,
                                       jstring feature_name, jstring address) {
  ALOGV("%s", __func__);

  if (!sBluetoothInterface) {
    ALOGW("%s: sBluetoothInterface is null.", __func__);
    return JNI_FALSE;
  }

  const char* tmp_addr = env->GetStringUTFChars(address, NULL);
  if (!tmp_addr) {
    ALOGW("%s: address is null.", __func__);
    return JNI_FALSE;
  }
  RawAddress bdaddr;
  bool success = RawAddress::FromString(tmp_addr, bdaddr);

  env->ReleaseStringUTFChars(address, tmp_addr);

  if (!success) {
    ALOGW("%s: address is invalid.", __func__);
    return JNI_FALSE;
  }

  const char* feature_name_str = env->GetStringUTFChars(feature_name, NULL);
  if (!feature_name_str) {
    ALOGW("%s: feature name is null.", __func__);
    return JNI_FALSE;
  }

  bool matched =
      sBluetoothInterface->interop_match_addr(feature_name_str, &bdaddr);
  env->ReleaseStringUTFChars(feature_name, feature_name_str);

  return matched ? JNI_TRUE : JNI_FALSE;
}

static jboolean interopMatchNameNative(JNIEnv* env, jclass clazz,
                                       jstring feature_name, jstring name) {
  ALOGV("%s", __func__);

  if (!sBluetoothInterface) {
    ALOGW("%s: sBluetoothInterface is null.", __func__);
    return JNI_FALSE;
  }

  const char* feature_name_str = env->GetStringUTFChars(feature_name, NULL);
  if (!feature_name_str) {
    ALOGW("%s: feature name is null.", __func__);
    return JNI_FALSE;
  }

  const char* name_str = env->GetStringUTFChars(name, NULL);
  if (!name_str) {
    ALOGW("%s: name is null.", __func__);
    env->ReleaseStringUTFChars(feature_name, feature_name_str);
    return JNI_FALSE;
  }

  bool matched =
      sBluetoothInterface->interop_match_name(feature_name_str, name_str);
  env->ReleaseStringUTFChars(feature_name, feature_name_str);
  env->ReleaseStringUTFChars(name, name_str);

  return matched ? JNI_TRUE : JNI_FALSE;
}

static jboolean interopMatchAddrOrNameNative(JNIEnv* env, jclass clazz,
                                             jstring feature_name,
                                             jstring address) {
  ALOGV("%s", __func__);

  if (!sBluetoothInterface) {
    ALOGW("%s: sBluetoothInterface is null.", __func__);
    return JNI_FALSE;
  }

  const char* tmp_addr = env->GetStringUTFChars(address, NULL);
  if (!tmp_addr) {
    ALOGW("%s: address is null.", __func__);
    return JNI_FALSE;
  }
  RawAddress bdaddr;
  bool success = RawAddress::FromString(tmp_addr, bdaddr);

  env->ReleaseStringUTFChars(address, tmp_addr);

  if (!success) {
    ALOGW("%s: address is invalid.", __func__);
    return JNI_FALSE;
  }

  const char* feature_name_str = env->GetStringUTFChars(feature_name, NULL);
  if (!feature_name_str) {
    ALOGW("%s: feature name is null.", __func__);
    return JNI_FALSE;
  }

  bool matched = sBluetoothInterface->interop_match_addr_or_name(
      feature_name_str, &bdaddr);
  env->ReleaseStringUTFChars(feature_name, feature_name_str);

  return matched ? JNI_TRUE : JNI_FALSE;
}

static void interopDatabaseAddRemoveAddrNative(JNIEnv* env, jclass clazz,
                                               jboolean do_add,
                                               jstring feature_name,
                                               jstring address, jint length) {
  ALOGV("%s", __func__);

  if (!sBluetoothInterface) {
    ALOGW("%s: sBluetoothInterface is null.", __func__);
    return;
  }

  if ((do_add == JNI_TRUE) && (length <= 0 || length > 6)) {
    ALOGE("%s: address length %d is invalid, valid length is [1,6]", __func__,
          length);
    return;
  }

  const char* tmp_addr = env->GetStringUTFChars(address, NULL);
  if (!tmp_addr) {
    ALOGW("%s: address is null.", __func__);
    return;
  }
  RawAddress bdaddr;
  bool success = RawAddress::FromString(tmp_addr, bdaddr);

  env->ReleaseStringUTFChars(address, tmp_addr);

  if (!success) {
    ALOGW("%s: address is invalid.", __func__);
    return;
  }

  const char* feature_name_str = env->GetStringUTFChars(feature_name, NULL);
  if (!feature_name_str) {
    ALOGW("%s: feature name is null.", __func__);
    return;
  }

  sBluetoothInterface->interop_database_add_remove_addr(
      (do_add == JNI_TRUE), feature_name_str, &bdaddr, (int)length);

  env->ReleaseStringUTFChars(feature_name, feature_name_str);
}

static void interopDatabaseAddRemoveNameNative(JNIEnv* env, jclass clazz,
                                               jboolean do_add,
                                               jstring feature_name,
                                               jstring name) {
  ALOGV("%s", __func__);

  if (!sBluetoothInterface) {
    ALOGW("%s: sBluetoothInterface is null.", __func__);
    return;
  }

  const char* feature_name_str = env->GetStringUTFChars(feature_name, NULL);
  if (!feature_name_str) {
    ALOGW("%s: feature name is null.", __func__);
    return;
  }

  const char* name_str = env->GetStringUTFChars(name, NULL);
  if (!name_str) {
    ALOGW("%s: name is null.", __func__);
    env->ReleaseStringUTFChars(feature_name, feature_name_str);
    return;
  }

  sBluetoothInterface->interop_database_add_remove_name(
      (do_add == JNI_TRUE), feature_name_str, name_str);

  env->ReleaseStringUTFChars(feature_name, feature_name_str);
  env->ReleaseStringUTFChars(name, name_str);
}

static JNINativeMethod sMethods[] = {
    /* name, signature, funcPtr */
    {"classInitNative", "()V", (void*)classInitNative},
@@ -1898,6 +2079,18 @@ static JNINativeMethod sMethods[] = {
    {"allowLowLatencyAudioNative", "(Z[B)Z", (void*)allowLowLatencyAudioNative},
    {"metadataChangedNative", "([BI[B)V", (void*)metadataChangedNative},
    {"isLogRedactionEnabled", "()Z", (void*)isLogRedactionEnabled},
    {"interopMatchAddrNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
     (void*)interopMatchAddrNative},
    {"interopMatchNameNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
     (void*)interopMatchNameNative},
    {"interopMatchAddrOrNameNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
     (void*)interopMatchAddrOrNameNative},
    {"interopDatabaseAddRemoveAddrNative",
     "(ZLjava/lang/String;Ljava/lang/String;I)V",
     (void*)interopDatabaseAddRemoveAddrNative},
    {"interopDatabaseAddRemoveNameNative",
     "(ZLjava/lang/String;Ljava/lang/String;)V",
     (void*)interopDatabaseAddRemoveNameNative},
};

int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) {
+1 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ public final class AbstractionLayer {

    static final int BT_PROPERTY_DYNAMIC_AUDIO_BUFFER = 0x10;
    static final int BT_PROPERTY_REMOTE_IS_COORDINATED_SET_MEMBER = 0x11;
    static final int BT_PROPERTY_WL_MEDIA_PLAYERS_LIST = 0x14;

    public static final int BT_DEVICE_TYPE_BREDR = 0x01;
    public static final int BT_DEVICE_TYPE_BLE = 0x02;
+48 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 * Copyright (C) 2016-2017 The Linux Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -96,6 +97,8 @@ class AdapterProperties {

    private static final int SCAN_MODE_CHANGES_MAX_SIZE = 10;
    private EvictingQueue<String> mScanModeChanges;
    private CopyOnWriteArrayList<String> mAllowlistedPlayers =
            new CopyOnWriteArrayList<String>();

    private int mProfilesConnecting, mProfilesConnected, mProfilesDisconnecting;
    private final HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState =
@@ -263,6 +266,7 @@ class AdapterProperties {
        mBondedDevices.clear();
        mScanModeChanges.clear();
        invalidateBluetoothCaches();
        mAllowlistedPlayers.clear();
    }

    private static void invalidateGetProfileConnectionStateCache() {
@@ -700,6 +704,24 @@ class AdapterProperties {
        }
    }

     /**
     * @return the mAllowlistedPlayers
     */
    String[] getAllowlistedMediaPlayers() {
        String[] AllowlistedPlayersList = new String[0];
        try {
            AllowlistedPlayersList = mAllowlistedPlayers.toArray(AllowlistedPlayersList);
        } catch (ArrayStoreException ee) {
            errorLog("Error retrieving Allowlisted Players array");
        }
        Log.d(TAG, "getAllowlistedMediaPlayers: numAllowlistedPlayers = "
                                        + AllowlistedPlayersList.length);
        for (int i = 0; i < AllowlistedPlayersList.length; i++) {
            Log.d(TAG, "players :" + AllowlistedPlayersList[i]);
        }
        return AllowlistedPlayersList;
    }

    long discoveryEndMillis() {
        return mDiscoveryEndMs;
    }
@@ -911,6 +933,15 @@ class AdapterProperties {
        }
    }

    void updateAllowlistedMediaPlayers(String playername) {
        Log.d(TAG, "updateAllowlistedMediaPlayers ");

        if (!mAllowlistedPlayers.contains(playername)) {
            Log.d(TAG, "Adding to Allowlisted Players list:" + playername);
            mAllowlistedPlayers.add(playername);
        }
    }

    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
    void adapterPropertyChangedCallback(int[] types, byte[][] values) {
        Intent intent;
@@ -999,6 +1030,23 @@ class AdapterProperties {
                        debugLog("mLocalIOCapabilityBLE set to " + mLocalIOCapabilityBLE);
                        break;

                    case AbstractionLayer.BT_PROPERTY_WL_MEDIA_PLAYERS_LIST:
                        int pos = 0;
                        for (int j = 0; j < val.length; j++) {
                            if (val[j] != 0) {
                                continue;
                            }
                            int name_len = j - pos;

                            byte[] buf = new byte[name_len];
                            System.arraycopy(val, pos, buf, 0, name_len);
                            String player_name = new String(buf, 0, name_len);
                            Log.d(TAG, "player_name: "  +  player_name);
                            updateAllowlistedMediaPlayers(player_name);
                            pos += (name_len + 1);
                        }
                        break;

                    default:
                        errorLog("Property change not handled in Java land:" + type);
                }
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 * Copyright (C) 2016-2017 The Linux Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -108,6 +109,7 @@ import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.a2dpsink.A2dpSinkService;
import com.android.bluetooth.bas.BatteryService;
import com.android.bluetooth.bass_client.BassClientService;
import com.android.bluetooth.btservice.InteropUtil.InteropFeature;
import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
import com.android.bluetooth.btservice.activityattribution.ActivityAttributionService;
import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreService;
@@ -5468,6 +5470,10 @@ public class AdapterService extends Service {
        return mAdapterProperties.isA2dpOffloadEnabled();
    }

    public String[] getAllowlistedMediaPlayers() {
        return mAdapterProperties.getAllowlistedMediaPlayers();
    }

    @VisibleForTesting
    BluetoothActivityEnergyInfo reportActivityInfo() {
        if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON
@@ -6246,6 +6252,35 @@ public class AdapterService extends Service {
        mRemoteDevices.updateBatteryLevel(device, batteryLevel);
    }

    public boolean interopMatchAddr(InteropFeature feature, String address) {
        return interopMatchAddrNative(feature.name(), address);
    }

    public boolean interopMatchName(InteropFeature feature, String name) {
        return interopMatchNameNative(feature.name(), name);
    }

    public boolean interopMatchAddrOrName(InteropFeature feature, String address) {
        return interopMatchAddrOrNameNative(feature.name(), address);
    }

    public void interopDatabaseAddAddr(InteropFeature feature,
            String address, int length) {
        interopDatabaseAddRemoveAddrNative(true, feature.name(), address, length);
    }

    public void interopDatabaseRemoveAddr(InteropFeature feature, String address) {
        interopDatabaseAddRemoveAddrNative(false, feature.name(), address, 0);
    }

    public void interopDatabaseAddName(InteropFeature feature, String name) {
        interopDatabaseAddRemoveNameNative(true, feature.name(), name);
    }

    public void interopDatabaseRemoveName(InteropFeature feature, String name) {
        interopDatabaseAddRemoveNameNative(false, feature.name(), name);
    }

    static native void classInitNative();

    native boolean initNative(boolean startRestricted, boolean isCommonCriteriaMode,
@@ -6343,6 +6378,14 @@ public class AdapterService extends Service {

    private native void metadataChangedNative(byte[] address, int key, byte[] value);

    private native boolean interopMatchAddrNative(String featureName, String address);
    private native boolean interopMatchNameNative(String featureName, String name);
    private native boolean interopMatchAddrOrNameNative(String featureName, String address);
    private native void interopDatabaseAddRemoveAddrNative(boolean doAdd,
            String featureName, String address, int length);
    private native void interopDatabaseAddRemoveNameNative(boolean doAdd,
            String featureBame, String name);

    // Returns if this is a mock object. This is currently used in testing so that we may not call
    // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up
    // calling finalize() which in turn calls System.exit() and the process crashes.
+218 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2022 The Android Open Source Project
 * Copyright (c) 2020 The Linux Foundation
 *
 * 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.bluetooth.btservice;

import android.util.Log;

/**
 * APIs of interoperability workaround utilities.
 * These APIs will call stack layer's interop APIs of interop.cc to do matching
 * or entry adding/removing.
 */
public class InteropUtil {
    private static final String TAG = "InteropUtil";

    /**
     * Add interop feature from device/include/interop.h to below InteropFeature if
     * this feature needs to be matched at java layer. Feature's name will be passed to
     * stack layer to do matching, so make sure that the added feature's name is exactly
     * same as that in device/include/interop.h.
     */
    public enum InteropFeature {
        INTEROP_NOT_UPDATE_AVRCP_PAUSED_TO_REMOTE,
        INTEROP_PHONE_POLICY_INCREASED_DELAY_CONNECT_OTHER_PROFILES,
        INTEROP_PHONE_POLICY_REDUCED_DELAY_CONNECT_OTHER_PROFILES,
        INTEROP_HFP_FAKE_INCOMING_CALL_INDICATOR,
        INTEROP_HFP_SEND_CALL_INDICATORS_BACK_TO_BACK,
        INTEROP_SETUP_SCO_WITH_NO_DELAY_AFTER_SLC_DURING_CALL,
        INTEROP_RETRY_SCO_AFTER_REMOTE_REJECT_SCO;
    }

    /**
     * Check if a given address matches a known interoperability workaround
     * identified by the interop feature.
     *
     * @param feature a given interop feature defined in {@link InteropFeature}.
     * @param address a given address to be matched.
     * @return true if matched, false otherwise.
     */
    public static boolean interopMatchAddr(InteropFeature feature, String address) {
        AdapterService adapterService = AdapterService.getAdapterService();
        if (adapterService == null) {
            Log.d(TAG, "interopMatchAddr: feature=" + feature.name()
                    + ", adapterService is null or vendor intf is not enabled");
            return false;
        }

        Log.d(TAG, "interopMatchAddr: feature=" + feature.name() + ", address=" + address);
        if (address == null) {
            return false;
        }

        boolean matched = adapterService.interopMatchAddr(feature, address);
        Log.d(TAG, "interopMatchAddr: matched=" + matched);
        return matched;
    }

    /**
     * Check if a given name matches a known interoperability workaround
     * identified by the interop feature.
     *
     * @param feature a given interop feature defined in {@link InteropFeature}.
     * @param name a given name to be matched.
     * @return true if matched, false otherwise.
     */
    public static boolean interopMatchName(InteropFeature feature, String name) {
        AdapterService adapterService = AdapterService.getAdapterService();
        if (adapterService == null) {
            Log.d(TAG, "interopMatchName: feature=" + feature.name()
                    + ", adapterService is null or vendor intf is not enabled");
            return false;
        }

        Log.d(TAG, "interopMatchName: feature=" + feature.name() + ", name=" + name);
        if (name == null) {
            return false;
        }

        boolean matched = adapterService.interopMatchName(feature, name);
        Log.d(TAG, "interopMatchName: matched=" + matched);
        return matched;
    }

    /**
     * Check if a given address or remote device name matches a known interoperability workaround
     * identified by the interop feature. remote device name will be fetched internally based on
     * the given address at stack layer.
     *
     * @param feature a given interop feature defined in {@link InteropFeature}.
     * @param address a given address to be matched.
     * @return true if matched, false otherwise
     */
    public static boolean interopMatchAddrOrName(InteropFeature feature, String address) {
        AdapterService adapterService = AdapterService.getAdapterService();
        if (adapterService == null) {
            Log.d(TAG, "interopMatchAddrOrName: feature=" + feature.name()
                    + ", adapterService is null or vendor intf is not enabled");
            return false;
        }

        Log.d(TAG, "interopMatchAddrOrName: feature=" + feature.name() + ", address=" + address);
        if (address == null) {
            return false;
        }

        boolean matched = adapterService.interopMatchAddrOrName(feature, address);
        Log.d(TAG, "interopMatchAddrOrName: matched=" + matched);
        return matched;
    }

    /**
     * Add a dynamic address interop database entry identified by the interop feature
     * for a device matching the first length bytes of addr.
     *
     * @param feature a given interop feature defined in {@link InteropFeature}.
     * @param address a given address to be added.
     * @param length the number of bytes of address to be stored,
     * length must be in [1,6], and usually it is 3.
     */
    public static void interopDatabaseAddAddr(InteropFeature feature,
            String address, int length) {
        AdapterService adapterService = AdapterService.getAdapterService();
        if (adapterService == null) {
            Log.d(TAG, "interopDatabaseAddAddr: feature=" + feature.name()
                    + ", adapterService is null or vendor intf is not enabled");
            return;
        }

        Log.d(TAG, "interopDatabaseAddAddr: feature=" + feature.name()
                + ", address=" + address + ", length=" + length);
        if (address == null || (length <= 0 || length > 6)) {
            return;
        }

        adapterService.interopDatabaseAddAddr(feature, address, length);
    }

    /**
     * Remove a dynamic address interop database entry identified by the interop feature
     * for a device matching the addr.
     *
     * @param feature a given interop feature defined in {@link InteropFeature}.
     * @param address a given address to be removed.
     */
    public static void interopDatabaseRemoveAddr(InteropFeature feature, String address) {
        AdapterService adapterService = AdapterService.getAdapterService();
        if (adapterService == null) {
            Log.d(TAG, "interopDatabaseRemoveAddr: feature=" + feature.name()
                    + ", adapterService is null or vendor intf is not enabled");
            return;
        }

        Log.d(TAG, "interopDatabaseRemoveAddr: feature=" + feature.name() + ", address=" + address);
        if (address == null) {
            return;
        }

        adapterService.interopDatabaseRemoveAddr(feature, address);
    }

    /**
     * Add a dynamic name interop database entry identified by the interop feature for the name.
     *
     * @param feature a given interop feature defined in {@link InteropFeature}.
     * @param name a given name to be added.
     */
    public static void interopDatabaseAddName(InteropFeature feature, String name) {
        AdapterService adapterService = AdapterService.getAdapterService();
        if (adapterService == null) {
            Log.d(TAG, "interopDatabaseAddName: feature=" + feature.name()
                    + ", adapterService is null or vendor intf is not enabled");
            return;
        }

        Log.d(TAG, "interopDatabaseAddName: feature=" + feature.name() + ", name=" + name);
        if (name == null) {
            return;
        }

        adapterService.interopDatabaseAddName(feature, name);
    }

    /**
     * Remove a dynamic name interop database entry identified by the interop feature for the name.
     *
     * @param feature a given interop feature defined in {@link InteropFeature}.
     * @param name a given name to be removed.
     */
    public static void interopDatabaseRemoveName(InteropFeature feature, String name) {
        AdapterService adapterService = AdapterService.getAdapterService();
        if (adapterService == null) {
            Log.d(TAG, "interopDatabaseRemoveName: feature=" + feature.name()
                    + ", adapterService is null or vendor intf is not enabled");
            return;
        }

        Log.d(TAG, "interopDatabaseRemoveName: feature=" + feature.name() + ", name=" + name);
        if (name == null) {
            return;
        }

        adapterService.interopDatabaseRemoveName(feature, name);
    }
}
Loading