Skip to content

Commit 0e2c4d1

Browse files
committed
stealth(identity): per-build neutral identity, icons & manifest minimization
1 parent 1e1c52b commit 0e2c4d1

27 files changed

Lines changed: 2312 additions & 31 deletions
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
xmlns:tools="http://schemas.android.com/tools"
3+
android:installLocation="auto">
4+
5+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
6+
<uses-permission android:name="android.permission.INTERNET" />
7+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
8+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
9+
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
10+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
11+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
12+
13+
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
14+
<!-- <uses-permission android:name="android.permission.USE_EXACT_ALARM" /> -->
15+
16+
<application
17+
android:name=".LanternApp"
18+
android:icon="${appIcon}"
19+
android:label="${appLabel}"
20+
android:usesCleartextTraffic="true"
21+
android:roundIcon="${appRoundIcon}">
22+
23+
<activity
24+
android:name=".MainActivity"
25+
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
26+
android:exported="true"
27+
android:hardwareAccelerated="true"
28+
android:launchMode="singleTask"
29+
android:taskAffinity=""
30+
android:screenOrientation="portrait"
31+
android:theme="@style/LaunchTheme"
32+
android:windowSoftInputMode="adjustResize">
33+
<!-- Specifies an Android theme to apply to this Activity as soon as
34+
the Android process has started. This theme is visible to the user
35+
while the Flutter UI initializes. After that, this theme continues
36+
to determine the Window background behind the Flutter UI. -->
37+
<meta-data
38+
android:name="io.flutter.embedding.android.NormalTheme"
39+
android:resource="@style/NormalTheme" />
40+
<intent-filter>
41+
<action android:name="android.intent.action.MAIN" />
42+
<category android:name="android.intent.category.LAUNCHER" />
43+
</intent-filter>
44+
<meta-data
45+
android:name="flutter_deeplinking_enabled"
46+
android:value="false" />
47+
48+
<intent-filter android:autoVerify="true">
49+
<action android:name="android.intent.action.VIEW" />
50+
<category android:name="android.intent.category.DEFAULT" />
51+
<category android:name="android.intent.category.BROWSABLE" />
52+
<data android:scheme="https" android:host="lantern.io" android:pathPrefix="/report-issue" />
53+
</intent-filter>
54+
<intent-filter android:autoVerify="true">
55+
<action android:name="android.intent.action.VIEW" />
56+
<category android:name="android.intent.category.DEFAULT" />
57+
<category android:name="android.intent.category.BROWSABLE" />
58+
<data android:scheme="https" android:host="lantern.io" android:pathPrefix="/auth" />
59+
</intent-filter>
60+
<!-- Custom scheme fallback for browsers that don't support Android App Links (e.g. Firefox) -->
61+
<intent-filter>
62+
<action android:name="android.intent.action.VIEW" />
63+
<category android:name="android.intent.category.DEFAULT" />
64+
<category android:name="android.intent.category.BROWSABLE" />
65+
<data android:scheme="lantern" android:host="auth" />
66+
</intent-filter>
67+
<intent-filter>
68+
<action android:name="android.intent.action.VIEW" />
69+
<category android:name="android.intent.category.DEFAULT" />
70+
<category android:name="android.intent.category.BROWSABLE" />
71+
<data android:scheme="lantern" android:host="report-issue" />
72+
</intent-filter>
73+
<intent-filter>
74+
<action android:name="android.intent.action.VIEW" />
75+
<category android:name="android.intent.category.DEFAULT" />
76+
<category android:name="android.intent.category.BROWSABLE" />
77+
<data android:scheme="lantern" android:host="private-server" />
78+
</intent-filter>
79+
<intent-filter android:autoVerify="true">
80+
<action android:name="android.intent.action.VIEW" />
81+
<category android:name="android.intent.category.DEFAULT" />
82+
<category android:name="android.intent.category.BROWSABLE" />
83+
<data android:scheme="https" android:host="lantern.io" android:pathPrefix="/private-server" />
84+
</intent-filter>
85+
<intent-filter android:autoVerify="true">
86+
<action android:name="android.intent.action.VIEW" />
87+
<category android:name="android.intent.category.DEFAULT" />
88+
<category android:name="android.intent.category.BROWSABLE" />
89+
<data android:scheme="https" android:host="www.lantern.io" android:pathPrefix="/report-issue" />
90+
</intent-filter>
91+
<intent-filter android:autoVerify="true">
92+
<action android:name="android.intent.action.VIEW" />
93+
<category android:name="android.intent.category.DEFAULT" />
94+
<category android:name="android.intent.category.BROWSABLE" />
95+
<data android:scheme="https" android:host="www.lantern.io" android:pathPrefix="/auth" />
96+
</intent-filter>
97+
<intent-filter android:autoVerify="true">
98+
<action android:name="android.intent.action.VIEW" />
99+
<category android:name="android.intent.category.DEFAULT" />
100+
<category android:name="android.intent.category.BROWSABLE" />
101+
<data android:scheme="https" android:host="www.lantern.io" android:pathPrefix="/private-server" />
102+
</intent-filter>
103+
104+
</activity>
105+
106+
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
107+
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
108+
<intent-filter>
109+
<action android:name="android.intent.action.BOOT_COMPLETED"/>
110+
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
111+
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
112+
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
113+
</intent-filter>
114+
</receiver>
115+
116+
<!-- Don't delete the meta-data below.
117+
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
118+
<meta-data
119+
android:name="flutterEmbedding"
120+
android:value="2" />
121+
122+
123+
<service
124+
android:name="foundation.bridge.SyncService"
125+
android:exported="false"
126+
android:foregroundServiceType="specialUse">
127+
<property
128+
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
129+
android:value="User-controlled local proxy connection" />
130+
</service>
131+
132+
<meta-data
133+
android:name="com.google.android.gms.wallet.api.enabled"
134+
android:value="true"/>
135+
136+
</application>
137+
<!-- Required to query activities that can process text, see:
138+
https://developer.android.com/training/package-visibility and
139+
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
140+
141+
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
142+
<queries>
143+
<intent>
144+
<action android:name="android.intent.action.PROCESS_TEXT" />
145+
<data android:mimeType="text/plain" />
146+
</intent>
147+
<intent>
148+
<action android:name="android.intent.action.VIEW" />
149+
<data android:scheme="alipays" />
150+
</intent>
151+
<intent>
152+
<action android:name="android.intent.action.VIEW" />
153+
<data android:scheme="alipay" />
154+
</intent>
155+
<package android:name="com.eg.android.AlipayGphone" />
156+
</queries>
157+
158+
159+
</manifest>

android/app/src/main/AndroidManifest.xml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,17 @@
1818

1919
<application
2020
android:name=".LanternApp"
21-
android:icon="@mipmap/ic_launcher"
22-
android:label="Lantern"
21+
android:icon="${appIcon}"
22+
android:label="${appLabel}"
2323
android:usesCleartextTraffic="true"
24-
android:roundIcon="@mipmap/ic_launcher_round">
24+
android:roundIcon="${appRoundIcon}">
2525

2626
<activity
2727
android:name=".MainActivity"
2828
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
2929
android:exported="true"
3030
android:hardwareAccelerated="true"
31+
android:label="${launcherLabel}"
3132
android:launchMode="singleTask"
3233
android:taskAffinity=""
3334
android:screenOrientation="portrait"
@@ -65,19 +66,19 @@
6566
<action android:name="android.intent.action.VIEW" />
6667
<category android:name="android.intent.category.DEFAULT" />
6768
<category android:name="android.intent.category.BROWSABLE" />
68-
<data android:scheme="lantern" android:host="auth" />
69+
<data android:scheme="${appAuthScheme}" android:host="auth" />
6970
</intent-filter>
7071
<intent-filter>
7172
<action android:name="android.intent.action.VIEW" />
7273
<category android:name="android.intent.category.DEFAULT" />
7374
<category android:name="android.intent.category.BROWSABLE" />
74-
<data android:scheme="lantern" android:host="report-issue" />
75+
<data android:scheme="${appAuthScheme}" android:host="report-issue" />
7576
</intent-filter>
7677
<intent-filter>
7778
<action android:name="android.intent.action.VIEW" />
7879
<category android:name="android.intent.category.DEFAULT" />
7980
<category android:name="android.intent.category.BROWSABLE" />
80-
<data android:scheme="lantern" android:host="private-server" />
81+
<data android:scheme="${appAuthScheme}" android:host="private-server" />
8182
</intent-filter>
8283
<intent-filter android:autoVerify="true">
8384
<action android:name="android.intent.action.VIEW" />
@@ -122,7 +123,6 @@
122123
android:name="flutterEmbedding"
123124
android:value="2" />
124125

125-
126126
<service
127127
android:name=".service.LanternVpnService"
128128
android:exported="false"
@@ -137,7 +137,7 @@
137137
android:name=".service.QuickTileService"
138138
android:directBootAware="true"
139139
android:exported="true"
140-
android:icon="@drawable/lantern_notification_icon"
140+
android:icon="${quickTileIcon}"
141141
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
142142
tools:targetApi="n">
143143
<intent-filter>

android/app/src/main/kotlin/org/getlantern/lantern/LanternApp.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import androidx.core.content.getSystemService
1212
import lantern.io.mobile.Mobile
1313

1414

15-
class LanternApp : Application() {
15+
open class LanternApp : Application() {
1616

1717
companion object {
1818
lateinit var application: LanternApp

android/app/src/main/kotlin/org/getlantern/lantern/notification/NotificationManager.kt

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import android.net.Uri
1111
import android.os.Build
1212
import androidx.core.app.NotificationCompat
1313
import androidx.core.content.getSystemService
14+
import org.getlantern.lantern.BuildConfig
1415
import org.getlantern.lantern.LanternApp
1516
import org.getlantern.lantern.MainActivity
1617
import org.getlantern.lantern.R
@@ -28,8 +29,6 @@ class NotificationHelper {
2829
private const val CHANNEL_DATA_USAGE = "data_usage"
2930
const val OPEN_URL = "SERVICE_OPEN_URL"
3031

31-
private const val VPN_DESC = "VPN"
32-
private const val DATA_USAGE_DESC = "Data Usage"
3332
var notificationManager = LanternApp.application.getSystemService<NotificationManager>()!!
3433
val flags =
3534
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
@@ -45,6 +44,7 @@ class NotificationHelper {
4544

4645
private lateinit var dataUsageNotificationChannel: NotificationChannel
4746
private lateinit var vpnNotificationChannel: NotificationChannel
47+
private val notificationSmallIconId: Int by lazy { resolveNotificationSmallIcon() }
4848

4949

5050
init {
@@ -59,14 +59,14 @@ class NotificationHelper {
5959
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
6060
vpnNotificationChannel = NotificationChannel(
6161
CHANNEL_VPN,
62-
VPN_DESC,
62+
BuildConfig.NOTIFICATION_CHANNEL_VPN,
6363
NotificationManager.IMPORTANCE_HIGH,
6464
)
6565
notificationManager.createNotificationChannel(vpnNotificationChannel)
6666

6767
dataUsageNotificationChannel = NotificationChannel(
6868
CHANNEL_DATA_USAGE,
69-
DATA_USAGE_DESC,
69+
BuildConfig.NOTIFICATION_CHANNEL_DATA_USAGE,
7070
NotificationManager.IMPORTANCE_HIGH,
7171
)
7272
notificationManager.createNotificationChannel(dataUsageNotificationChannel)
@@ -96,14 +96,14 @@ class NotificationHelper {
9696
return NotificationCompat.Builder(LanternApp.application, CHANNEL_VPN)
9797
.setShowWhen(false)
9898
.setOngoing(true)
99-
.setContentTitle("Lantern")
100-
.setContentText("Lantern VPN is running")
99+
.setContentTitle(BuildConfig.NOTIFICATION_TITLE)
100+
.setContentText(BuildConfig.NOTIFICATION_CONNECTED_TEXT)
101101
.setOnlyAlertOnce(true)
102-
.setSmallIcon(R.drawable.lantern_notification_icon)
102+
.setSmallIcon(notificationSmallIconId)
103103
.addAction(
104104
NotificationCompat.Action.Builder(
105105
android.R.drawable.ic_menu_close_clear_cancel,
106-
"Disconnect",
106+
BuildConfig.NOTIFICATION_DISCONNECT_ACTION,
107107
disconnectVPN()
108108
).build()
109109
)
@@ -123,10 +123,10 @@ class NotificationHelper {
123123
return NotificationCompat.Builder(LanternApp.application, CHANNEL_VPN)
124124
.setShowWhen(false)
125125
.setOngoing(true)
126-
.setContentTitle("Lantern")
127-
.setContentText("Starting Lantern VPN...")
126+
.setContentTitle(BuildConfig.NOTIFICATION_TITLE)
127+
.setContentText(BuildConfig.NOTIFICATION_STARTING_TEXT)
128128
.setOnlyAlertOnce(true)
129-
.setSmallIcon(R.drawable.lantern_notification_icon)
129+
.setSmallIcon(notificationSmallIconId)
130130
.setContentIntent(contentIntent)
131131
.setSilent(true)
132132
.build()
@@ -209,7 +209,7 @@ class NotificationHelper {
209209
.setContentTitle(notification.title)
210210
.setContentText(notification.body)
211211
.setOnlyAlertOnce(true)
212-
.setSmallIcon(R.drawable.lantern_notification_icon)
212+
.setSmallIcon(notificationSmallIconId)
213213
.setCategory(NotificationCompat.CATEGORY_EVENT)
214214
.setPriority(NotificationCompat.PRIORITY_HIGH)
215215
.setAutoCancel(true)
@@ -234,4 +234,19 @@ class NotificationHelper {
234234
notificationManager.notify(notification.typeID, builder.build())
235235
}
236236

237+
private fun resolveNotificationSmallIcon(): Int {
238+
val configured = BuildConfig.NOTIFICATION_SMALL_ICON.removePrefix("@")
239+
val parts = configured.split("/", limit = 2)
240+
if (parts.size == 2) {
241+
val resolved = LanternApp.application.resources.getIdentifier(
242+
parts[1],
243+
parts[0],
244+
LanternApp.application.packageName,
245+
)
246+
if (resolved != 0) {
247+
return resolved
248+
}
249+
}
250+
return R.drawable.lantern_notification_icon
251+
}
237252
}

android/app/src/main/kotlin/org/getlantern/lantern/service/LanternVpnService.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ import org.getlantern.lantern.utils.toIpPrefix
4545
* it should not include any logic that needs to be connected with any activity.
4646
* everything should be done in independent
4747
*/
48-
class LanternVpnService :
48+
open class LanternVpnService :
4949
VpnService(),
5050
PlatformInterfaceWrapper {
5151
companion object {
5252
private const val TAG = "LanternVpnService"
53-
private const val sessionName = "LanternVpn"
53+
private val sessionName = BuildConfig.VPN_SESSION_NAME
5454
const val ACTION_START_RADIANCE = "com.getlantern.START_RADIANCE"
5555
const val ACTION_START_VPN = "org.getlantern.START_VPN"
5656
const val ACTION_CONNECT_TO_SERVER = "org.getlantern.CONNECT_TO_SERVER"

0 commit comments

Comments
 (0)