Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
KieronQuinn committed Feb 9, 2022
1 parent 242bccb commit 482c00a
Show file tree
Hide file tree
Showing 67 changed files with 1,787 additions and 2 deletions.
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/.idea/misc.xml
.DS_Store
/build
/captures
.cxx

# Built application files
*.apk
*.ap_
Expand Down
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
# SIMNumberSetter

# SIM Number Setter

SIM Number Setter is a small Xposed module that invokes normally unused Android System code to set
the "subscriber number" on the device's SIM card. This is the number displayed in the system
settings, and used in apps such as Google Messages, as well as being available to third party apps
with sufficient permissions.

The number is not always set by carriers (leaving "Unknown"), or can be lost or invalid after
porting a number to a different SIM.

This small app allows you to fix it, permanently, using a rooted device with Xposed.

**If you don't have a rooted device, or don't want to root your main device, you may wish to
consider rooting an old device, and temporarily putting your SIM into that device, using this app,
and then putting it back in your main device - the fixed number will travel with it**

### Important Notice

Changing the SIM number is semi-permanent: the number change will survive reboots, uninstalling this
app, even switching the SIM to a different device, but can be changed again at any time using this
app.

SIM Number Setter does NOT:
- Change your actual phone number, no matter what you enter.
- Unblock a network blocked SIM.\n- Give you free data or calls.
- Change your IMEI.

SIM Number Setter uses the built-in Android methods to write data to the SIM.
The app nor the developer are not responsible for issues with the process, including any damage to
the SIM or network issues.

### Screenshots

[![Screenshots](https://i.imgur.com/UNKADmrl.png)](https://i.imgur.com/UNKADmr.png)

### Download

[Download from releases page](https://github.com/KieronQuinn/SIMNumberSetter/releases)
1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
51 changes: 51 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}

android {
compileSdk 32

defaultConfig {
applicationId "com.kieronquinn.app.simnumbersetter"
minSdk 26
targetSdk 32
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}

dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.github.KieronQuinn:MonetCompat:0.4.1'
implementation 'androidx.palette:palette:1.0.0'
implementation 'io.insert-koin:koin-android:3.1.5'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
implementation 'com.github.topjohnwu.libsu:core:3.2.1'
compileOnly project(path: ':systemstubs')
compileOnly 'de.robv.android.xposed:api:82'
}
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
20 changes: 20 additions & 0 deletions app/release/output-metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.kieronquinn.app.simnumbersetter",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0",
"outputFile": "app-release.apk"
}
],
"elementType": "File"
}
47 changes: 47 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.kieronquinn.app.simnumbersetter">

<uses-permission android:name="android.permission.DUMP"
tools:ignore="ProtectedPermissions" />

<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:name=".Application"
android:supportsRtl="true"
android:theme="@style/Theme.PhoneNumberSetter">
<activity
android:name="com.kieronquinn.app.simnumbersetter.ui.activities.MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<meta-data
android:name="xposedmodule"
android:value="true"/>
<meta-data
android:name="xposeddescription"
android:value="@string/xposed_desc"/>
<meta-data
android:name="xposedminversion"
android:value="90"/>
<meta-data
android:name="xposedscope"
android:resource="@array/scope"/>

</application>

<queries>
<package android:name="com.android.phone"/>
</queries>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.kieronquinn.app.simnumbersetter;

import android.os.Message;

interface IPhoneNumberSetter {

boolean setLine1Number(String number, in Message onComplete);
String getLine1Number();

}
1 change: 1 addition & 0 deletions app/src/main/assets/xposed_init
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.kieronquinn.app.simnumbersetter.Xposed
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.kieronquinn.app.simnumbersetter

import android.app.Application
import com.kieronquinn.app.simnumbersetter.repositories.*
import com.kieronquinn.app.simnumbersetter.ui.screens.main.MainViewModel
import com.kieronquinn.app.simnumbersetter.ui.screens.main.MainViewModelImpl
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.context.startKoin
import org.koin.dsl.module

class Application: Application() {

private val repositories = module {
single<PermissionRepository> { PermissionRepositoryImpl(get(), get()) }
single<RootRepository> { RootRepositoryImpl() }
single<ServiceRepository> { ServiceRepositoryImpl(get()) }
}

private val viewModels = module {
viewModel<MainViewModel> { MainViewModelImpl(get(), get(), get()) }
}

override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@Application)
modules(repositories, viewModels)
}
}

}
40 changes: 40 additions & 0 deletions app/src/main/java/com/kieronquinn/app/simnumbersetter/Xposed.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.kieronquinn.app.simnumbersetter

import android.content.Intent
import com.kieronquinn.app.simnumbersetter.service.PhoneNumberSetterService
import com.kieronquinn.app.simnumbersetter.utils.extensions.checkSecurity
import de.robv.android.xposed.IXposedHookLoadPackage
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedHelpers
import de.robv.android.xposed.callbacks.XC_LoadPackage

/**
* Xposed hook to allow binding to TelephonyDebugService (an exported, but protected service in
* com.android.phone), returning [IPhoneNumberSetter]. This can then be accessed via the UI
* and used to query and set the number.
*/
class Xposed: IXposedHookLoadPackage {

override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
if(lpparam.packageName != "com.android.phone") return
XposedHelpers.findAndHookMethod(
"com.android.phone.TelephonyDebugService",
lpparam.classLoader,
"onBind",
Intent::class.java,
object: XC_MethodHook() {
override fun beforeHookedMethod(param: MethodHookParam) {
super.beforeHookedMethod(param)
param.onBind(param.args[0] as Intent)
}
}
)
}

private fun XC_MethodHook.MethodHookParam.onBind(intent: Intent) {
if(intent.checkSecurity()){
result = PhoneNumberSetterService()
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.kieronquinn.app.simnumbersetter.repositories

import android.content.Context
import android.content.pm.PackageManager
import com.kieronquinn.app.simnumbersetter.BuildConfig
import com.kieronquinn.app.simnumbersetter.repositories.PermissionRepository.Companion.PERMISSION_DUMP
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

interface PermissionRepository {

companion object {
internal const val PERMISSION_DUMP = "android.permission.DUMP"
}

suspend fun grantDumpPermission(): Boolean

}

class PermissionRepositoryImpl(
private val context: Context,
private val rootRepository: RootRepository
): PermissionRepository {

private fun hasDumpPermission(): Boolean {
return context.checkCallingOrSelfPermission(PERMISSION_DUMP) == PackageManager.PERMISSION_GRANTED
}

private suspend fun runGrantCommand() {
rootRepository.runRootCommand(
"pm grant ${BuildConfig.APPLICATION_ID} $PERMISSION_DUMP"
)
}

override suspend fun grantDumpPermission(): Boolean {
return withContext(Dispatchers.IO) {
if(!hasDumpPermission()){
runGrantCommand()
hasDumpPermission()
}else true
}
}

}
Loading

0 comments on commit 482c00a

Please sign in to comment.