Skip to content

Commit

Permalink
Location: Correctly report location activity from apps
Browse files Browse the repository at this point in the history
  • Loading branch information
mar-v-in committed May 16, 2024
1 parent ad2ed4d commit d1bfa90
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ class LocationRequestManager(private val context: Context, override val lifecycl
suspend fun remove(oldBinder: IBinder) {
lock.withLock {
oldBinder.unlinkToDeath(this, 0)
if (binderRequests.remove(oldBinder) != null) recalculateRequests()
val holder = binderRequests.remove(oldBinder)
if (holder != null) {
holder.cancel()
recalculateRequests()
}
}
notifyRequestDetailsUpdated()
}
Expand Down Expand Up @@ -398,7 +402,7 @@ class LocationRequestManager(private val context: Context, override val lifecycl
get() = request.intervalMillis < 60000 || effectivePriority == PRIORITY_HIGH_ACCURACY

fun update(callback: ILocationCallback, request: LocationRequest): LocationRequestHolder {
val changedGranularity = request.granularity != this.request.granularity
val changedGranularity = request.granularity != this.request.granularity || request.granularity == GRANULARITY_PERMISSION_LEVEL
if (changedGranularity && shouldPersistOp) context.finishAppOpForEffectiveGranularity(clientIdentity, effectiveGranularity)
this.callback = callback
this.request = request
Expand All @@ -421,7 +425,6 @@ class LocationRequestManager(private val context: Context, override val lifecycl
} else {
if (!context.checkAppOpForEffectiveGranularity(clientIdentity, effectiveGranularity)) throw RuntimeException("Lack of permission")
}
// TODO: Register app op watch
return this
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import android.content.pm.PackageManager
import android.os.Binder
import android.os.Build.VERSION.SDK_INT
import android.os.Process
import android.os.WorkSource
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.AppOpsManagerCompat
import androidx.core.content.getSystemService
import com.google.android.gms.common.Feature
Expand All @@ -23,7 +21,6 @@ import com.google.android.gms.location.internal.ClientIdentity
import com.google.android.gms.location.internal.IFusedLocationProviderCallback
import org.microg.gms.common.PackageUtils
import org.microg.gms.location.GranularityUtil
import org.microg.gms.utils.WorkSourceUtil

const val TAG = "LocationManager"

Expand Down Expand Up @@ -92,13 +89,17 @@ fun LocationRequest.verify(context: Context, clientIdentity: ClientIdentity) {

}

@RequiresApi(19)
fun appOpFromEffectiveGranularity(effectiveGranularity: @Granularity Int) = when (effectiveGranularity) {
fun checkAppOpFromEffectiveGranularity(effectiveGranularity: @Granularity Int) = when (effectiveGranularity) {
Granularity.GRANULARITY_FINE -> AppOpsManager.OPSTR_FINE_LOCATION
Granularity.GRANULARITY_COARSE -> AppOpsManager.OPSTR_COARSE_LOCATION
else -> throw IllegalArgumentException()
}

fun allAppOpsFromEffectiveGranularity(effectiveGranularity: @Granularity Int) = when (effectiveGranularity) {
Granularity.GRANULARITY_FINE -> listOf(AppOpsManager.OPSTR_FINE_LOCATION, AppOpsManager.OPSTR_MONITOR_LOCATION, AppOpsManager.OPSTR_MONITOR_HIGH_POWER_LOCATION)
Granularity.GRANULARITY_COARSE -> listOf(AppOpsManager.OPSTR_COARSE_LOCATION, AppOpsManager.OPSTR_MONITOR_LOCATION)
else -> throw IllegalArgumentException()
}

fun getEffectiveGranularity(requestGranularity: @Granularity Int, permissionGranularity: @Granularity Int) = when {
requestGranularity == Granularity.GRANULARITY_PERMISSION_LEVEL && permissionGranularity == Granularity.GRANULARITY_PERMISSION_LEVEL -> Granularity.GRANULARITY_FINE
Expand All @@ -111,59 +112,44 @@ fun Context.noteAppOpForEffectiveGranularity(
effectiveGranularity: @Granularity Int,
message: String? = null
): Boolean {
return if (SDK_INT >= 19) {
try {
val op = appOpFromEffectiveGranularity(effectiveGranularity)
noteAppOp(op, clientIdentity, message)
} catch (e: Exception) {
Log.w(TAG, "Could not notify appops", e)
true
}
} else {
return try {
val op = checkAppOpFromEffectiveGranularity(effectiveGranularity)
noteAppOp(op, clientIdentity, message)
} catch (e: Exception) {
Log.w(TAG, "Could not notify appops", e)
true
}
}

fun Context.checkAppOpForEffectiveGranularity(clientIdentity: ClientIdentity, effectiveGranularity: @Granularity Int): Boolean {
return if (SDK_INT >= 19) {
try {
val op = appOpFromEffectiveGranularity(effectiveGranularity)
checkAppOp(op, clientIdentity)
} catch (e: Exception) {
Log.w(TAG, "Could not check appops", e)
true
}
} else {
return try {
val op = checkAppOpFromEffectiveGranularity(effectiveGranularity)
checkAppOp(op, clientIdentity)
} catch (e: Exception) {
Log.w(TAG, "Could not check appops", e)
true
}
}

fun Context.startAppOpForEffectiveGranularity(clientIdentity: ClientIdentity, effectiveGranularity: @Granularity Int): Boolean {
return if (SDK_INT >= 19) {
try {
val op = appOpFromEffectiveGranularity(effectiveGranularity)
checkAppOp(op, clientIdentity)
} catch (e: Exception) {
Log.w(TAG, "Could not start appops", e)
true
}
} else {
return try {
val ops = allAppOpsFromEffectiveGranularity(effectiveGranularity)
startAppOps(ops, clientIdentity)
} catch (e: Exception) {
Log.w(TAG, "Could not start appops", e)
true
}
}

fun Context.finishAppOpForEffectiveGranularity(clientIdentity: ClientIdentity, effectiveGranularity: @Granularity Int) {
if (SDK_INT >= 19) {
try {
val op = appOpFromEffectiveGranularity(effectiveGranularity)
finishAppOp(op, clientIdentity)
} catch (e: Exception) {
Log.w(TAG, "Could not finish appops", e)
}
try {
val ops = allAppOpsFromEffectiveGranularity(effectiveGranularity)
finishAppOps(ops, clientIdentity)
} catch (e: Exception) {
Log.w(TAG, "Could not finish appops", e)
}
}

@RequiresApi(19)
private fun Context.checkAppOp(
op: String,
clientIdentity: ClientIdentity
Expand All @@ -177,11 +163,16 @@ private fun Context.checkAppOp(
true
}

@RequiresApi(19)
private fun Context.startAppOps(
ops: List<String>,
clientIdentity: ClientIdentity,
message: String? = null
) = ops.all { startAppOp(it, clientIdentity, message) }

private fun Context.startAppOp(
op: String,
clientIdentity: ClientIdentity,
message: String?
message: String? = null
) = try {
if (SDK_INT >= 30 && clientIdentity.attributionTag != null) {
getSystemService<AppOpsManager>()?.startOpNoThrow(op, clientIdentity.uid, clientIdentity.packageName, clientIdentity.attributionTag!!, message)
Expand All @@ -196,7 +187,11 @@ private fun Context.startAppOp(
}
} == AppOpsManager.MODE_ALLOWED

@RequiresApi(19)
private fun Context.finishAppOps(
ops: List<String>,
clientIdentity: ClientIdentity
) = ops.forEach { finishAppOp(it, clientIdentity) }

private fun Context.finishAppOp(
op: String,
clientIdentity: ClientIdentity
Expand All @@ -214,7 +209,6 @@ private fun Context.finishAppOp(
}
}

@RequiresApi(19)
private fun Context.noteAppOp(
op: String,
clientIdentity: ClientIdentity,
Expand Down

0 comments on commit d1bfa90

Please sign in to comment.