From f3b5ebf4eb3e6fbd53662de2ef736deebf89a395 Mon Sep 17 00:00:00 2001 From: ale5000 <15793015+ale5000-git@users.noreply.github.com> Date: Sun, 10 Mar 2024 19:51:37 +0100 Subject: [PATCH] Location: Fix exceptions in CellDetailsSource when the ACCESS_FINE_LOCATION permission isn't granted (#2220) --- .../network/cell/CellDetailsSource.kt | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 play-services-location/core/provider/src/main/kotlin/org/microg/gms/location/network/cell/CellDetailsSource.kt diff --git a/play-services-location/core/provider/src/main/kotlin/org/microg/gms/location/network/cell/CellDetailsSource.kt b/play-services-location/core/provider/src/main/kotlin/org/microg/gms/location/network/cell/CellDetailsSource.kt new file mode 100644 index 00000000..8e809f95 --- /dev/null +++ b/play-services-location/core/provider/src/main/kotlin/org/microg/gms/location/network/cell/CellDetailsSource.kt @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: 2023 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.location.network.cell + +import android.annotation.SuppressLint +import android.content.Context +import android.os.Build.VERSION.SDK_INT +import android.os.WorkSource +import android.telephony.CellInfo +import android.telephony.TelephonyManager +import android.util.Log +import androidx.core.content.getSystemService + +private const val TAG = "CellDetailsSource" + +class CellDetailsSource(private val context: Context, private val callback: CellDetailsCallback) { + fun enable() = Unit + fun disable() = Unit + + @SuppressLint("MissingPermission") + fun startScan(workSource: WorkSource?) { + val telephonyManager = context.getSystemService() ?: return + if (SDK_INT >= 29) { + try { + telephonyManager.requestCellInfoUpdate(context.mainExecutor, object : TelephonyManager.CellInfoCallback() { + override fun onCellInfo(cells: MutableList) { + val details = cells.map(CellInfo::toCellDetails).map { it.repair(context) }.filter(CellDetails::isValid) + if (details.isNotEmpty()) callback.onCellDetailsAvailable(details) + } + }) + } catch (e: SecurityException) { + // It may trigger a SecurityException if the ACCESS_FINE_LOCATION permission isn't granted + Log.w(TAG, "requestCellInfoUpdate in startScan failed", e) + } + + return + } else if (SDK_INT >= 17) { + val allCellInfo: List? = try { + telephonyManager.allCellInfo + } catch (e: SecurityException) { + // It may trigger a SecurityException if the ACCESS_FINE_LOCATION permission isn't granted + Log.w(TAG, "allCellInfo in startScan failed", e) + null + } + if (allCellInfo != null) { + val details = allCellInfo.map(CellInfo::toCellDetails).map { it.repair(context) }.filter(CellDetails::isValid) + if (details.isNotEmpty()) { + callback.onCellDetailsAvailable(details) + return + } + } + } + val networkOperator = telephonyManager.networkOperator + if (networkOperator != null && networkOperator.length > 4) { + val mcc = networkOperator.substring(0, 3).toIntOrNull() + val mnc = networkOperator.substring(3).toIntOrNull() + val detail: CellDetails? = try { + telephonyManager.cellLocation?.toCellDetails(mcc, mnc) + } catch (e: SecurityException) { + // It may trigger a SecurityException if the ACCESS_FINE_LOCATION permission isn't granted + Log.w(TAG, "cellLocation in startScan failed", e) + null + } + if (detail?.isValid == true) callback.onCellDetailsAvailable(listOf(detail)) + } + } + + companion object { + fun create(context: Context, callback: CellDetailsCallback): CellDetailsSource = CellDetailsSource(context, callback) + } +}