如何更新已创建的 Wi-Fi 配置(或“UID XXX 无权更新 [Wi-Fi] 配置错误”)?

2024-01-07

我正在开发一个管理 Wi-Fi 连接的应用程序。我的场景如下:假设整个大楼都有一个名为“testing-tls”的 Wi-Fi 网络。我的应用程序应该能够仅连接到选定的接入点(基于 BSSID 或 MAC ID)。我们用TLS 认证验证用户的机制(自定义 CA 证书)。

我可以通过应用程序建立连接,但当我尝试连接到不同的接入点(不同的 BSSID)时失败。尽管我以编程方式创建了 Wi-Fi 配置,但在首次成功连接后仍无法更新配置。我已经在奥利奥和棉花糖中测试了我的应用程序。但是,我在奥利奥中遇到问题(不确定牛轧糖)。我开始想知道配置创建后是否可以更新。

这些是我正在遵循的步骤:

1)创建WifiConfiguration对象

private WifiConfiguration createWifiConfiguration() {
    WifiConfiguration config = new WifiConfiguration();
    config.SSID = "\"testing-tls\"";
    config.priority = 1;
    config.status = WifiConfiguration.Status.ENABLED;
    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP;
    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
    config.enterpriseConfig.setIdentity(identityName);
    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);

    PKCS12ParseInfo parseInfo;
    try {
        parseInfo = CertificateUtils.parsePKCS12Certificate(
                       certificateFilePath, identityPassword);
        if (parseInfo != null) {
            config.enterpriseConfig.setClientKeyEntry(parseInfo.getPrivateKey(),
                           parseInfo.getCertificate());
            return config;
        }
        return null;
    } catch (KeyStoreException | NoSuchAlgorithmException | IOException |
                   CertificateException | UnrecoverableKeyException | KeyManagementException e1) {
        Timber.e("WifiMonitorService, Fail to parse the input certificate: %s", e1.toString());
        Toast.makeText(this, "Error occurred", Toast.LENGTH_SHORT).show();
        return null;
    }
}

2)尝试建立连接

private void establishWifiConnection(String result) {
    Timber.d("WifiMonitorService, establishing WifiConnection");

    WifiConfiguration configuration = createWifiConfiguration();
    if (configuration != null) {
        // result contains a mac id - 00:45:69:c5:34:f2
        configuration.BSSID = result;

        int networkId = wifiManager.addNetwork(configuration);
        if (networkId == -1) {
            networkId = getExistingNetworkId(wifiSsid);
            // Add a new configuration to the db
            if (networkId == -1) {
                Timber.e("Couldn't add network with SSID");
                Toast.makeText(this, "Wifi configuration error", Toast.LENGTH_SHORT).show();
                return;
            }
        }
        Timber.i("WifiMonitorService, # addNetwork returned: %d", networkId);
        wifiManager.saveConfiguration();
        wifiManager.enableNetwork(networkId, true);
        wifiManager.reassociate();
    } else {
        Toast.makeText(this, "Wifi conf Error occurred", Toast.LENGTH_SHORT).show();
    }
}

3) 获取退出网络 ID(如果存在)

private int getExistingNetworkId(String ssid) {
    List<WifiConfiguration> configuredNetworks  = 
    wifiManager.getConfiguredNetworks();
    if (configuredNetworks != null) {
        for (WifiConfiguration existingConfig : configuredNetworks) {
            if (existingConfig.SSID.equals("\"testing-tls\"")) {
                return existingConfig.networkId;
            }
        }
    }
    return -1;
}

清单权限如下:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />

<uses-feature android:name="android.hardware.wifi" />
<uses-feature android:name="android.hardware.camera" />

<permission
   android:name="android.permission.INTERACT_ACROSS_USERS"
   android:protectionLevel="signature" />

错误:我总是得到UID 10189 does not have permission to update configuration error in Oreo

2018-12-28 12:23:44.571 1320-1847/? E/WifiConfigManager: UID 10189 does not have permission to update configuration "testing-tls"WPA_EAP
2018-12-28 12:23:44.571 1320-1847/? I/WifiStateMachine: connectToUserSelectNetwork Allowing uid 10189 with insufficient permissions to connect=1

调查

经过深入研究源代码,我发现了addOrUpdateNetwork中的方法Wifi配置管理器 https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/android-8.0.0_r21/service/java/com/android/server/wifi/WifiConfigManager.java class.

实施情况addOrUpdateNetwork https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/android-8.0.0_r21/service/java/com/android/server/wifi/WifiConfigManager.java#1054, 在标签中android_8.0.0_r21(内部版本号 OPD1.170816.010) https://source.android.com/setup/start/build-numbers如下:

  • 首先检查我们是否已经有一个具有提供的网络 id 或 configKey 的网络
  • 如果未找到现有网络,请验证配置并添加。
  • 如果找到现有网络,则更新网络配置。在此之前,请检查应用程序是否具有更新网络所需的权限。

AddOrUpdateNetwork内部调用一个名为canModifyNetwork https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/android-8.0.0_r21/service/java/com/android/server/wifi/WifiConfigManager.java#654:

/**
 * Checks if |uid| has permission to modify the provided configuration.
 *
 * @param config         WifiConfiguration object corresponding to the network to be modified.
 * @param uid            UID of the app requesting the modification.
 * @param ignoreLockdown Ignore the configuration lockdown checks for connection attempts.
 */
private boolean canModifyNetwork(WifiConfiguration config, int uid, boolean ignoreLockdown) {
    // Passpoint configurations are generated and managed by PasspointManager. They can be
    // added by either PasspointNetworkEvaluator (for auto connection) or Settings app
    // (for manual connection), and need to be removed once the connection is completed.
    // Since it is "owned" by us, so always allow us to modify them.
    if (config.isPasspoint() && uid == Process.WIFI_UID) {
        return true;
    }
    // EAP-SIM/AKA/AKA' network needs framework to update the anonymous identity provided
    // by authenticator back to the WifiConfiguration object.
    // Since it is "owned" by us, so always allow us to modify them.
    if (config.enterpriseConfig != null
            && uid == Process.WIFI_UID
            && TelephonyUtil.isSimEapMethod(config.enterpriseConfig.getEapMethod())) {
        return true;
    }
    final DevicePolicyManagerInternal dpmi = LocalServices.getService(
            DevicePolicyManagerInternal.class);
    final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid,
            DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
    // If |uid| corresponds to the device owner, allow all modifications.
    if (isUidDeviceOwner) {
        return true;
    }
    final boolean isCreator = (config.creatorUid == uid);
    // Check if the |uid| holds the |NETWORK_SETTINGS| permission if the caller asks us to
    // bypass the lockdown checks.
    if (ignoreLockdown) {
        return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
    }
    // Check if device has DPM capability. If it has and |dpmi| is still null, then we
    // treat this case with suspicion and bail out.
    if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)
            && dpmi == null) {
        Log.w(TAG, "Error retrieving DPMI service.");
        return false;
    }
    // WiFi config lockdown related logic. At this point we know uid is NOT a Device Owner.
    final boolean isConfigEligibleForLockdown = dpmi != null && dpmi.isActiveAdminWithPolicy(
            config.creatorUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
    if (!isConfigEligibleForLockdown) {
        return isCreator || mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
    }
    final ContentResolver resolver = mContext.getContentResolver();
    final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver,
            Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0;
    return !isLockdownFeatureEnabled
            && mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
}

据我所知,只有以下 uid 有权修改网络配置。

  1. 系统应用程序
  2. 设备所有者
  3. 创建者(由于某种原因失败)

我在这两部手机中遇到了相同的行为。

  1. 像素 2(奥利奥 8.0.0)
  2. 三星 J8(奥利奥 8.0.0)

此外,三星 J8 总是显示此警告:

CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certificate path not found

问题:

  • How can an already created Wi-Fi configuration be updated programmatically?
    • 在 Wi-Fi 内部数据库中创建 Wi-Fi 配置后是否还可以更新它?
    • 更新或启用配置之前是否必须断开 Wi-Fi?

经过深入研究源代码,终于找到了我的问题的答案。

问题:创建后可以更新配置吗?

Answer:是的,Android 操作系统允许您更新从应用程序创建的配置。当我打电话时wifiManager.addNetwork() https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r21/wifi/java/android/net/wifi/WifiManager.java#1063,在日志窗口中打印了以下语句。

2019-01-04 12:23:16.168 1328-3114/? I/addOrUpdateNetwork:  uid = 10190 SSID "testing-tls" nid=-1
2019-01-04 12:23:16.169 1328-1851/? V/WifiConfigManager: Adding/Updating network testing-tls
2019-01-04 12:23:16.193 1328-1851/? D/WifiConfigManager: addOrUpdateNetworkInternal: added/updated config. netId=6 configKey="testing-tls"WPA_EAP uid=10190 name=in.ac.iisc.wifimonitoring vendorAP=false hiddenSSID=false autoReconnect=1
2019-01-04 12:23:16.204 1328-1851/? D/WifiConfigStore: Writing to stores completed in 7 ms.
2019-01-04 12:23:16.205 1328-1851/? D/WifiIssueDetector: report htime=2019-01-04_12:23:16 time=1546584796205 rid=105 callBy=in.ac.iisc.wifimonitoring apiName=addOrUpdateNetwork netid=6 callUid=in.ac.iisc.wifimonitoring
2019-01-04 12:23:16.206 15873-15873/in.ac.iisc.wifimonitoring I/WifiMonitorService: WifiMonitorService, #addNetwork returned: 6

问:Oreo 中“UID 10189 无权更新配置错误”是什么意思?

Answer:更新配置后,我们必须调用wifimanager.enableNetwork() https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r21/wifi/java/android/net/wifi/WifiManager.java#1263方法来建立与所需接入点的连接。 EnableNetwork()的工作流程如下。

  1. WifiManager.enableNetwork() 内部调用同步启用网络() https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/master/service/java/com/android/server/wifi/WifiStateMachine.java#1741WifiStateMachine 类的方法。

Wifi状态机 https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/master/service/java/com/android/server/wifi/WifiStateMachine.java是跟踪 Wifi 连接状态的核心类。所有事件处理和连接状态的所有更改均在此类中启动。

  1. SyncEnableNetwork() 方法发送 CMD_ENABLE_NETWORK 消息到连接模式状态类 https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/master/service/java/com/android/server/wifi/WifiStateMachine.java#3803.

  2. 如果disableOthers为true,调用连接到用户选择网络() https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/master/service/java/com/android/server/wifi/WifiStateMachine.java#1134方法并传递 networkId,调用 UID 并强制重新连接 [始终为 false - 硬编码值] 作为参数。

  3. 如果应用程序没有更新配置的所有必要权限[使用检查并更新LastUid() https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/android-8.0.0_r21/service/java/com/android/server/wifi/WifiConfigManager.java#1532中的方法WifiConfigManager类 https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/android-8.0.0_r21/service/java/com/android/server/wifi/WifiConfigManager.java- 仅对系统设置/sysui 应用程序返回 true] 或者如果网络启用失败,将打印以下语句。

2018-12-28 12:23:44.571 1320-1847/? E/WifiConfigManager: UID 10189 does not have permission to update configuration "testing-tls"WPA_EAP
2018-12-28 12:23:44.571 1320-1847/? I/WifiStateMachine: connectToUserSelectNetwork Allowing uid 10189 with insufficient permissions to connect=1

Note:checkAndUpdateLastUid() 方法已在 Android Pie 中重命名为 updateLastConnectUid()。他们也稍微修改了其功能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何更新已创建的 Wi-Fi 配置(或“UID XXX 无权更新 [Wi-Fi] 配置错误”)? 的相关文章

  • 在旧版本的 API 上更改 ContentObserver Onchange 上的 uri [重复]

    这个问题在这里已经有答案了 可能的重复 如何获取内容观察器中插入行的 URI https stackoverflow com questions 8432800 how to get uri of inserted row in my co
  • 按大小、日期、名称等在回收器视图中排序并记住选择

    我正在制作图库应用程序 我想为其添加排序功能 我可以使用以下命令在运行时对项目进行排序Comparator但问题是 每当我退出应用程序时 列表都会再次从数据库中出来 并且所有列表都未排序 我想在我的应用程序中提供按日期 大小 名称等排序的选
  • 启动时的 Android pin 活动

    我有一个应用程序 它将自身注册为默认启动器 并在启动时自动固定自身 安装应用程序时这一切都正常 它会自行固定 并且只有后退按钮可见 问题是 当设备首次启动时 它无法正确固定 我多次看到一系列 屏幕固定 和 屏幕取消固定 的 toast 主页
  • Android O 的 WiFi 对等发现问题

    我正在开发一个 Android 应用程序 它使用 WiFi 直接 进行服务发现和 P2P 对等发现 连接 我的开发环境如下 Android Studio 3 0 Beta 4 Build AI 171 4304935 built on Au
  • 未安装 newrelic 的应用程序上出现 NoClassDefFoundError

    我已经使用他们的 Eclipse 指南为我的 Android 应用程序安装了 newrelic 它在该应用程序上运行正常 现在 如果我创建一个简单的 hello world 项目 我将收到 NoClassDefFoundError 我该如何
  • Android 崩溃报告库(Froyo 之前)[重复]

    这个问题在这里已经有答案了 你知道 Android 的崩溃报告库吗 我不想花很多时间来编写自己的报告系统 输出可以发送到电子邮件或某种服务器 我知道 Google 在 Froyo 中引入了崩溃报告 但我想要一些适用于旧版本系统的东西 我们来
  • 在应用程序启动期间更改主题的最快方法

    目前 我确实在我的应用程序中根据用户最后的选择提供了 2 个主题 深色主题和浅色主题 在主要活动启动期间 我将执行以下操作 public class MyFragmentActivity extends FragmentActivity O
  • 如何在phonegap上使用GCM处理android中的多个推送通知

    当推送通知到达时 如果用户无法查看该通知 他收到另一条通知 之前的通知正在更新为新的 但它不应该更新为最新的 我们需要单独显示每个通知 这可以使用 GCM 吗 我已经使用Phonegap来开发应用程序 PushPlugin 支持在有效负载中
  • Android 上的 Chrome 强制隐藏地址栏

    我最近开发了一个获取混合 http https 内容的网站 因此 我总是将地址栏显示在顶部 它不会像其他网站那样自动隐藏 这就是我要说的 This https planetkde org 是网站的链接 内容是从各种来源获取的 因此无法过滤非
  • android:widgetLayout 和 android:layout 之间的区别?

    我得到一些奇怪的配置 其中 widgetLayout 配置列表项的内部空间 而布局配置整个项目列表和屏幕背景 有人能真正解释一下什么是 widgetLayout 吗 android layout 整个首选项的布局 包括标题 摘要和小部件 a
  • 如何增加颤振中切屑的宽度

    我想增加宽度Chip 我怎样才能实现这个目标 Chip elevation 6 0 backgroundColor Colors white shape RoundedRectangleBorder borderRadius BorderR
  • 如何在将数据发送到 Firebase 数据库之前对其进行加密?

    我正在使用 Firebase 实时数据库制作聊天应用程序 我知道 Firebase 非常安全 只要您的规则正确 但我自己可以阅读使用我的应用程序的人的所有聊天记录 我想阻止这种情况 为此我需要一种解密和加密方法 我尝试使用凯撒解密 但失败了
  • getViewByID 对于 Listview 返回 null

    我的 main xml 如下
  • 使用 IntelliJ / Android Studio 调试基于 gradle 的单元测试

    我正在使用robolectric gradle 插件 https github com robolectric robolectric gradle plugin为 Android 编写单元测试 到目前为止 除了能够使用 Android S
  • 有没有办法模拟小部件或屏幕特定位置的触摸?

    我想触摸或点击小部件上的某处 而不让用户在此时明确触摸屏幕 有什么办法可以做到吗 我已经检查了SO答案 有些人建议使用 集成测试 但在未物理或以某种方式连接到笔记本电脑的设备上无法执行 集成测试 无法找到更好的措辞 我还尝试进行 hitTe
  • Android:如何为我的应用程序播放的任何音乐文件创建淡入/淡出音效?

    我正在开发的应用程序播放音乐文件 如果计时器到期 我希望音乐淡出 我怎么做 我正在使用 MediaPlayer 播放音乐 音乐文件位于我的应用程序的原始文件夹中 这是我的 Android MediaPlayer 的整个处理程序类 查看 pl
  • Android 中的字符串加密

    我正在使用代码进行加密和加密 它没有给出字符串结果 字节数组未转换为字符串 我几乎尝试了所有方法将字节数组转换为字符 但没有给出结果 public class EncryptionTest extends Activity EditText
  • 无法读取解析推送通知包数据

    我尝试使用 Parse 推送通知服务发送自定义数据 但从 Bundle 中提取时总是返回 null 值 自定义广播接收器 Override public void onReceive Context context Intent inten
  • 如何更改焦点/按下时图像按钮的色调

    我有一个ImageButton在我的应用程序中 当按钮打开时我需要更改图像的色调pressed focused 我有ImageButton设置为获取其src来自 XML 文件 如下所示
  • 使用 Android 的 Mobile Vision API 扫描二维码

    我跟着这个tutorial http code tutsplus com tutorials reading qr codes using the mobile vision api cms 24680关于如何构建可以扫描二维码的 Andr

随机推荐