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

Commit b5eacdde authored by Guillaume Jacquart's avatar Guillaume Jacquart
Browse files

Add setVpnPackageAuthorization permission handling

parent f3d3eb63
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -4,12 +4,12 @@ plugins {
}

android {
    compileSdkVersion 30
    compileSdkVersion 29

    defaultConfig {
        applicationId "foundation.e.eprivacymoduledemo"
        minSdkVersion 24
        targetSdkVersion 30
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

+1 −0
Original line number Diff line number Diff line
@@ -5,5 +5,6 @@
        <permission name="android.permission.WATCH_APPOPS" />
        <permission name="android.permission.GET_APP_OPS_STATS" />
        <permission name="android.permission.WRITE_SECURE_SETTINGS" />
        <permission name="android.permission.CONTROL_VPN" />
    </privapp-permissions>
</permissions>
 No newline at end of file
+4 −3
Original line number Diff line number Diff line
@@ -5,9 +5,8 @@

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"
        tools:ignore="ProtectedPermissions"
        />



    <application
        android:allowBackup="true"
@@ -25,6 +24,8 @@
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".FakeLocationActivity"/>

    </application>

</manifest>
 No newline at end of file
+167 −0
Original line number Diff line number Diff line
package foundation.e.eprivacymoduledemo

import android.app.AppOpsManager
import android.content.Context
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import android.os.Process.myUid
import android.util.Log
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import foundation.e.eprivacymoduledemo.databinding.FakeLocationActivityBinding
import foundation.e.privacymodules.location.FakeLocation
import foundation.e.privacymodules.location.IFakeLocation
import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
import foundation.e.privacymodules.permissions.data.AppOpModes
import foundation.e.privacymodules.permissions.data.ApplicationDescription

class FakeLocationActivity : AppCompatActivity() {

    private val fakeLocationModule: IFakeLocation by lazy { FakeLocation(this) }
    private val permissionsModule by lazy { PermissionsPrivacyModule(this) }

    private lateinit var binding: FakeLocationActivityBinding

    private val appDesc by lazy {
        ApplicationDescription(
            packageName = packageName,
            uid = myUid(),
            label = getString(R.string.app_name),
            icon = null
        )
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.fake_location_activity)

        getActionBar()?.setDisplayHomeAsUpEnabled(true);

        binding.view = this
        updateData("")
    }

    override fun onResume() {
        super.onResume()
        updateData("")
    }



    fun updateData(mockedLocation: String) {
        binding.granted = permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) == AppOpModes.ALLOWED

        binding.mockedLocation = mockedLocation
    }

    private val listener = object: LocationListener {
        override fun onLocationChanged(location: Location?) {
            binding.currentLocation = if (location == null) "null"
            else "lat: ${location.latitude} - lon: ${location.longitude}"
        }

        override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
            TODO("Not yet implemented")
        }

        override fun onProviderEnabled(provider: String?) {
            binding.providerInfo = "onProdivderEnabled: $provider"
        }

        override fun onProviderDisabled(provider: String?) {
            binding.providerInfo = "onProdivderDisabled: $provider"
        }
    }

    fun onClickToggleListenLocation(view: View?) {
        //permissionsModule.toggleDangerousPermission(appDesc, android.Manifest.permission.ACCESS_FINE_LOCATION, true)

//        permissionsModule.setAppOpMode(
//            appDesc, AppOpsManager.OPSTR_COARSE_LOCATION,
//            AppOpModes.ALLOWED
//        )
//        permissionsModule.setAppOpMode(
//            appDesc, AppOpsManager.OPSTR_FINE_LOCATION,
//            AppOpModes.ALLOWED
//        )


        val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager

        if (binding.toggleListenLocation.isChecked) {
            try {
                Log.e("DebugLoc", "requestLocationUpdates")
                locationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, // TODO: tight this with fakelocation module.
                    1000L,
                    1f,
                    listener
                )
                binding.currentLocation = "listening started"
            } catch (se: SecurityException) {
                Log.e("DebugLoc", "Missing permission", se)
            }
        } else {
            locationManager.removeUpdates(listener)
            binding.currentLocation = "no listening"
        }
    }


    fun onClickPermission(view: View?) {
        val manualAction = permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION,
            AppOpModes.ALLOWED)

        if (manualAction == null) {
            updateData("")
        } else {
            //dev mode disabled
            val alertDialog = AlertDialog.Builder(this)
            alertDialog
                .setTitle(manualAction.title)
                .setMessage(manualAction.instructions)
                .setPositiveButton("Ok") { dialog, which ->
                    startActivityForResult(manualAction.intent, 0)
                }
                .setNegativeButton("Cancel") { dialog, which ->
                    //user cancel
                }
            alertDialog.create().show()
        }
    }

    fun onClickReset(view: View?) {
        try {
            fakeLocationModule.stopFakeLocation()
        } catch(e: Exception) {
            Log.e("FakeLoc", "Can't stop FakeLocation", e)
        }
    }

    private fun setFakeLocation(latitude: Double, longitude: Double) {
        try {
            fakeLocationModule.startFakeLocation()
        } catch(e: Exception) {
            Log.e("FakeLoc", "Can't startFakeLocation", e)
        }
        fakeLocationModule.setFakeLocation(latitude, longitude)
        updateData("lat: ${latitude} - lon: ${longitude}")
    }

    fun onClickParis(view: View?) {
        setFakeLocation(48.8502282, 2.3542286)
    }

    fun onClickLondon(view: View?) {
        setFakeLocation(51.5287718, -0.2416803)
    }

    fun onClickAmsterdam(view: View?) {
        setFakeLocation(52.3547498, 4.8339211)
    }
}
 No newline at end of file
+35 −142
Original line number Diff line number Diff line
package foundation.e.eprivacymoduledemo

import android.app.AppOpsManager
import android.app.AppOpsManager.*
import android.content.Context
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import androidx.appcompat.app.AppCompatActivity
import android.content.Intent
import android.net.IConnectivityManager
import android.os.Bundle
import android.os.Process.myUid
import android.util.Log
import android.os.ServiceManager
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import foundation.e.eprivacymoduledemo.databinding.ActivityMainBinding
import foundation.e.privacymodules.location.FakeLocation
import foundation.e.privacymodules.location.IFakeLocation
import foundation.e.eprivacymoduledemo.databinding.MainActivityBinding
import android.os.UserHandle
import android.util.Log
import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
import foundation.e.privacymodules.permissions.data.AppOpModes
import foundation.e.privacymodules.permissions.data.ApplicationDescription

class MainActivity : AppCompatActivity() {
import java.lang.Exception
import java.security.PermissionCollection

    private val fakeLocationModule: IFakeLocation by lazy { FakeLocation(this) }
    private val permissionsModule by lazy { PermissionsPrivacyModule(this) }

    private lateinit var binding: ActivityMainBinding

    private val appDesc by lazy {
        ApplicationDescription(
            packageName = packageName,
            uid = myUid(),
            label = getString(R.string.app_name),
            icon = null
        )
    }

class MainActivity : AppCompatActivity() {
    private lateinit var binding: MainActivityBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        getActionBar()?.setDisplayHomeAsUpEnabled(true);

        binding = DataBindingUtil.setContentView(this, R.layout.main_activity)
        binding.view = this
        updateData("")
    }

    override fun onResume() {
        super.onResume()
        updateData("")
    }



    fun updateData(mockedLocation: String) {
        binding.granted = permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) == AppOpModes.ALLOWED

        binding.mockedLocation = mockedLocation
    }

    private val listener = object: LocationListener {
        override fun onLocationChanged(location: Location?) {
            binding.currentLocation = if (location == null) "null"
            else "lat: ${location.latitude} - lon: ${location.longitude}"
    fun onClickFakeLocation(view: View) {
        startActivity(Intent(this, FakeLocationActivity::class.java))
    }

        override fun onProviderEnabled(provider: String?) {
            binding.providerInfo = "onProdivderEnabled: $provider"
    fun onClickPermissions(view: View) {
        //startActivity(Intent(this, PermissionsListActivity::class.java))
    }

        override fun onProviderDisabled(provider: String?) {
            binding.providerInfo = "onProdivderDisabled: $provider"
        }
    }

    fun onClickToggleListenLocation(view: View?) {
        //permissionsModule.toggleDangerousPermission(appDesc, android.Manifest.permission.ACCESS_FINE_LOCATION, true)

//        permissionsModule.setAppOpMode(
//            appDesc, AppOpsManager.OPSTR_COARSE_LOCATION,
//            AppOpModes.ALLOWED
//        )
//        permissionsModule.setAppOpMode(
//            appDesc, AppOpsManager.OPSTR_FINE_LOCATION,
//            AppOpModes.ALLOWED
//        )


        val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager

        if (binding.toggleListenLocation.isChecked) {
            try {
                Log.e("DebugLoc", "requestLocationUpdates")
                locationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, // TODO: tight this with fakelocation module.
                    1000L,
                    1f,
                    listener
                )
                binding.currentLocation = "listening started"
            } catch (se: SecurityException) {
                Log.e("DebugLoc", "Missing permission", se)
            }
        } else {
            locationManager.removeUpdates(listener)
            binding.currentLocation = "no listening"
        }
    }


    fun onClickPermission(view: View?) {
        val manualAction = permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION,
            AppOpModes.ALLOWED)

        if (manualAction == null) {
            updateData("")
        } else {
            //dev mode disabled
            val alertDialog = AlertDialog.Builder(this)
            alertDialog
                .setTitle(manualAction.title)
                .setMessage(manualAction.instructions)
                .setPositiveButton("Ok") { dialog, which ->
                    startActivityForResult(manualAction.intent, 0)
                }
                .setNegativeButton("Cancel") { dialog, which ->
                    //user cancel
                }
            alertDialog.create().show()
        }
    }

    fun onClickReset(view: View?) {
        try {
            fakeLocationModule.stopFakeLocation()
        } catch(e: Exception) {
            Log.e("FakeLoc", "Can't stop FakeLocation", e)
        }
    }

    private fun setFakeLocation(latitude: Double, longitude: Double) {
        try {
            fakeLocationModule.startFakeLocation()
        } catch(e: Exception) {
            Log.e("FakeLoc", "Can't startFakeLocation", e)
        }
        fakeLocationModule.setFakeLocation(latitude, longitude)
        updateData("lat: ${latitude} - lon: ${longitude}")
    }

    fun onClickParis(view: View?) {
        setFakeLocation(48.8502282, 2.3542286)
    }

    fun onClickLondon(view: View?) {
        setFakeLocation(51.5287718, -0.2416803)
    }
    fun onClickQuickTest(view: View) {
        val permissionsPrivacyModule = PermissionsPrivacyModule(this)
        permissionsPrivacyModule.setVpnPackageAuthorization("foundation.e.privacycentralapp.e")
//        val mService: IConnectivityManager = IConnectivityManager.Stub.asInterface(
//            ServiceManager.getService(Context.CONNECTIVITY_SERVICE))
//
//        val mPackage = "foundation.e.privacycentralapp.e"
//        try {
//            if (mService.prepareVpn(null, mPackage, UserHandle.myUserId())) {
//                // Authorize this app to initiate VPN connections in the future without user
//                // intervention.
//                mService.setVpnPackageAuthorization(mPackage, UserHandle.myUserId(), true)
//                binding.quickTestLog = "Done!"
//            }
//        } catch (e: Exception) {
//            Log.e("QuickTest", "onClick", e)
//            binding.quickTestLog = e.message
//        }

    fun onClickAmsterdam(view: View?) {
        setFakeLocation(52.3547498, 4.8339211)
    }
}
Loading