I looked a little bit in Android source code and found following code
public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED);
return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
}
/**
* Thread-safe method for enabling or disabling a single location provider.
* @param cr the content resolver to use
* @param provider the location provider to enable or disable
* @param enabled true if the provider should be enabled
*/
public static final void setLocationProviderEnabled(ContentResolver cr,
String provider, boolean enabled) {
// to ensure thread safety, we write the provider name with a '+' or '-'
// and let the SettingsProvider handle it rather than reading and modifying
// the list of enabled providers.
if (enabled) {
provider = "+" + provider;
} else {
provider = "-" + provider;
}
putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);
}
I believe, if you have root access then you can both read and write Settings.Secure. this way you should be able to control GPS (setLocationProviderEnabled).
However, as I understand it won't turn off a GPS hardware, just will ignore this location provider.
I am not aware of interfaces which will talk to GPS and turn off hardware. However, another option which you have is to disable kernel module responsible for GPS (I am not aware of it's name).
Update 1
I checked how WRITE_SECURE_SETTIONS is defined in Android (4.1). Here it is
<permission android:name="android.permission.WRITE_SECURE_SETTINGS"
android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
android:protectionLevel="signature|system|development"
android:label="@string/permlab_writeSecureSettings"
android:description="@string/permdesc_writeSecureSettings" />
Based on "system" level. Add it to the manifest of your application, copy this application to the system image (you will need to mount it as writable) and you should be good to go.
And one more thing. uid shell has this permission.
<assign-permission name="android.permission.WRITE_SECURE_SETTINGS" uid="shell" />
I don't remember exactly, but there is some way to temporary change uid (if you are root).
I was it somewhere in Android code. So, you can change uid to shell, do something and change it back.
Update 2
I found this method of chaing uid.
If you download AOSP, you can find how it used in native library in coulpe of places
./base/cmds/screenshot/screenshot.c
It does setuid(AID_SHELL);
./native/cmds/dumpstate/dumpstate.c
setuid(AID_SHELL)
and it in couple of other places.
I think you should experiment with it to get AID_SHELL group which has WRITE_SECURE_SETTINGS permission.
Update 3
I am not sure about the details. I believe there should a native driver and unix device for gps hardware. However, it could be named differently on different devices.
You can try to use rmmod linux command to remove some module. I believe it should disable gps.