Skip to content

Commit

Permalink
Location: ask for permissions if not granted at time of request
Browse files Browse the repository at this point in the history
  • Loading branch information
mar-v-in committed Sep 12, 2023
1 parent 1100129 commit 666361a
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
android:name="org.microg.gms.auth.phone.AskPermissionActivity"
android:exported="false"
android:process=":ui"
android:theme="@style/Theme.AppCompat.DayNight.Dialog.Alert.NoActionBar" />
android:theme="@style/Theme.Translucent" />

<service
android:name="org.microg.gms.auth.phone.SmsRetrieverService"
Expand Down
11 changes: 11 additions & 0 deletions play-services-base/core/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,15 @@
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<style name="Theme.Translucent" parent="Theme.AppCompat.DayNight.Dialog.Alert.NoActionBar">
<item name="background">@android:color/transparent</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
</style>
</resources>
2 changes: 1 addition & 1 deletion play-services-fido/core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
android:exported="false"
android:process=":ui"
android:theme="@style/Theme.Fido.Translucent" />
android:theme="@style/Theme.Translucent" />
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class AuthenticatorGetInfoResponse(
uvModality = obj.get(18)?.AsInt32Value(),
certifications = obj.get(19)?.entries?.mapNotNull { runCatching { it.key.AsString() to it.value.AsInt32Value() }.getOrNull() }?.toMap(),
remainingDiscoverableCredentials = obj.get(20)?.AsInt32Value(),
vendorPrototypeConfigCommands = obj.get(20)?.AsInt32Sequence()?.toList(),
vendorPrototypeConfigCommands = obj.get(21)?.AsInt32Sequence()?.toList(),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class AuthenticatorActivity : AppCompatActivity(), TransportHandlerCallback {
if (instantTransport != null && instantTransport.transport in INSTANT_SUPPORTED_TRANSPORTS) {
window.setBackgroundDrawable(ColorDrawable(0))
window.statusBarColor = Color.TRANSPARENT
setTheme(R.style.Theme_Fido_Translucent)
setTheme(org.microg.gms.base.core.R.style.Theme_Translucent)
}
}

Expand Down
19 changes: 0 additions & 19 deletions play-services-fido/core/src/main/res/values/styles.xml

This file was deleted.

51 changes: 30 additions & 21 deletions play-services-location/core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
<?xml version="1.0" encoding="utf-8"?><!--
~ SPDX-FileCopyrightText: 2020 microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.BODY_SENSORS"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BODY_SENSORS" />

<uses-permission android:name="android.permission.UPDATE_DEVICE_STATS"
tools:ignore="ProtectedPermissions"/>
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS"
tools:ignore="ProtectedPermissions"/>
<uses-permission android:name="android.permission.WATCH_APPOPS"
tools:ignore="ProtectedPermissions"/>
<uses-permission
android:name="android.permission.UPDATE_DEVICE_STATS"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.UPDATE_APP_OPS_STATS"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.WATCH_APPOPS"
tools:ignore="ProtectedPermissions" />

<application>
<activity
android:name="org.microg.gms.location.manager.AskPermissionActivity"
android:process=":ui"
android:theme="@style/Theme.Translucent"
android:exported="false" />

<service
android:name="org.microg.gms.location.manager.LocationManagerService"
android:exported="true">
android:name="org.microg.gms.location.manager.LocationManagerService"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.location.internal.GoogleLocationManagerService.START"/>
<action android:name="com.google.android.location.internal.GoogleLocationManagerService.START" />
</intent-filter>
</service>
<service android:name="org.microg.gms.location.reporting.ReportingAndroidService"
android:exported="true">
<service
android:name="org.microg.gms.location.reporting.ReportingAndroidService"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.location.reporting.service.START"/>
<action android:name="com.google.android.gms.location.reporting.service.START"/>
<action android:name="com.google.android.location.reporting.service.START" />
<action android:name="com.google.android.gms.location.reporting.service.START" />

<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/

package org.microg.gms.location.manager

import android.content.Intent
import android.os.Bundle
import android.os.Message
import android.os.Messenger
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.os.bundleOf

const val EXTRA_MESSENGER = "messenger"
const val EXTRA_PERMISSIONS = "permissions"
const val EXTRA_GRANT_RESULTS = "results"

private const val REQUEST_CODE_PERMISSION = 120

class AskPermissionActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val permissions = intent?.getStringArrayExtra(EXTRA_PERMISSIONS) ?: emptyArray()
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE_PERMISSION)
}

private fun sendReply(code: Int = RESULT_OK, extras: Bundle = Bundle.EMPTY) {
intent?.getParcelableExtra<Messenger>(EXTRA_MESSENGER)?.let {
runCatching {
it.send(Message.obtain().apply {
what = code
data = extras
})
}
}
setResult(code, Intent().apply { putExtras(extras) })
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (requestCode == REQUEST_CODE_PERMISSION) {
sendReply(extras = bundleOf(EXTRA_GRANT_RESULTS to grantResults))
finish()
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ class LastLocationCapsule(private val context: Context) {
Log.w(TAG, e)
// Ignore
}
fetchFromSystem()
}

fun fetchFromSystem() {
val locationManager = context.getSystemService<LocationManager>() ?: return
try {
locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)?.let { updateCoarseLocation(it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
package org.microg.gms.location.manager

import android.Manifest
import android.app.Activity
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_MUTABLE
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Location
import android.location.LocationManager
import android.os.*
import android.os.Build.VERSION.SDK_INT
import android.os.IBinder
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.core.location.LocationListenerCompat
import androidx.core.location.LocationManagerCompat
Expand All @@ -29,6 +30,10 @@ import com.google.android.gms.location.Granularity.GRANULARITY_COARSE
import com.google.android.gms.location.Granularity.GRANULARITY_FINE
import com.google.android.gms.location.Priority.PRIORITY_HIGH_ACCURACY
import com.google.android.gms.location.internal.ClientIdentity
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.microg.gms.location.*
import org.microg.gms.utils.IntentCacheManager
import java.io.PrintWriter
Expand All @@ -45,6 +50,8 @@ class LocationManager(private val context: Context, private val lifecycle: Lifec
private val gpsLocationListener by lazy { LocationListenerCompat { updateGpsLocation(it) } }
private val networkLocationListener by lazy { LocationListenerCompat { updateNetworkLocation(it) } }
private var boundToSystemNetworkLocation: Boolean = false
private val activePermissionRequestLock = Mutex()
private var activePermissionRequest: Deferred<Boolean>? = null

val deviceOrientationManager = DeviceOrientationManager(context, lifecycle)

Expand Down Expand Up @@ -72,6 +79,7 @@ class LocationManager(private val context: Context, private val lifecycle: Lifec
// No last location available at requested granularity due to lack of permission
null
} else {
ensurePermissions()
val preLocation = lastLocationCapsule.getLocation(effectiveGranularity, request.maxUpdateAgeMillis)
val processedLocation = postProcessor.process(preLocation, effectiveGranularity, clientIdentity.isGoogle(context))
if (!context.noteAppOpForEffectiveGranularity(clientIdentity, effectiveGranularity)) {
Expand Down Expand Up @@ -103,6 +111,7 @@ class LocationManager(private val context: Context, private val lifecycle: Lifec

suspend fun addBinderRequest(clientIdentity: ClientIdentity, binder: IBinder, callback: ILocationCallback, request: LocationRequest) {
request.verify(context, clientIdentity)
ensurePermissions()
requestManager.add(binder, clientIdentity, callback, request, lastLocationCapsule)
}

Expand All @@ -123,6 +132,7 @@ class LocationManager(private val context: Context, private val lifecycle: Lifec

suspend fun addIntentRequest(clientIdentity: ClientIdentity, pendingIntent: PendingIntent, request: LocationRequest) {
request.verify(context, clientIdentity)
ensurePermissions()
requestManager.add(pendingIntent, clientIdentity, request, lastLocationCapsule)
}

Expand Down Expand Up @@ -243,6 +253,46 @@ class LocationManager(private val context: Context, private val lifecycle: Lifec
lastLocationCapsule.getLocation(GRANULARITY_FINE, Long.MAX_VALUE)?.let { deviceOrientationManager.onLocationChanged(it) }
}

private suspend fun ensurePermissions(): Boolean {
if (SDK_INT < 23)
return true

val permissions = mutableListOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION)
if (SDK_INT >= 29) permissions.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION)

if (permissions.all { ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED })
return true

val (completable, deferred) = activePermissionRequestLock.withLock {
if (activePermissionRequest == null) {
val completable = CompletableDeferred<Boolean>()
activePermissionRequest = completable
completable to activePermissionRequest!!
} else {
null to activePermissionRequest!!
}
}
if (completable != null) {
val intent = Intent(context, AskPermissionActivity::class.java)
intent.putExtra(EXTRA_MESSENGER, Messenger(object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
if (msg.what == Activity.RESULT_OK) {
lastLocationCapsule.fetchFromSystem()
onRequestManagerUpdated()
val grantResults = msg.data?.getIntArray(EXTRA_GRANT_RESULTS) ?: IntArray(0)
completable.complete(grantResults.size == permissions.size && grantResults.all { it == PackageManager.PERMISSION_GRANTED })
} else {
completable.complete(false)
}
}
}))
intent.putExtra(EXTRA_PERMISSIONS, permissions.toTypedArray())
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
}
return deferred.await()
}

fun dump(writer: PrintWriter) {
writer.println("Location availability: ${lastLocationCapsule.locationAvailability}")
writer.println("Last coarse location: ${postProcessor.process(lastLocationCapsule.getLocation(GRANULARITY_COARSE, Long.MAX_VALUE), GRANULARITY_COARSE, true)}")
Expand Down

0 comments on commit 666361a

Please sign in to comment.