### Configure Xposed Module Metadata and Scope in AndroidManifest.xml
Source: https://context7.com/canyie/settingsfirewall/llms.txt
This XML snippet configures an Android application as an Xposed module. It includes essential metadata such as module status, description, minimum Xposed version, and the scope of hooks. It also requests the necessary permission to query all installed packages.
```xml
```
--------------------------------
### Manage Firewall Targets in Main Activity - Java
Source: https://context7.com/canyie/settingsfirewall/llms.txt
This Java code snippet demonstrates the MainActivity for the Settings Firewall project. It handles the initialization of the firewall service, loading and displaying a list of applications, and managing user interactions such as toggling firewall targets and navigating to an editor for individual app settings. Dependencies include Android Activity, View, Bundle, Intent, and the custom ISettingsFirewall service.
```java
public class MainActivity extends Activity {
private ISettingsFirewall service;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
service = App.getService(this);
if (service == null) {
// Module not activated
findViewById(R.id.not_activated_msg).setVisibility(View.VISIBLE);
return;
}
// Load and display app list
ListView listView = findViewById(R.id.list);
AppListAdapter adapter = new AppListAdapter(this, App.getSortedList(this, service));
listView.setAdapter(adapter);
}
// Handle checkbox toggle
public void onItemChecked(AppInfo appInfo, boolean checked) {
try {
appInfo.enabled = checked;
service.setTarget(appInfo.uid, checked);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
// Handle item click to edit replacements
public void onItemClicked(AppInfo appInfo) {
startActivity(new Intent(this, SettingsEditActivity.class)
.putExtra(SettingsEditActivity.KEY_UID, appInfo.uid)
.putExtra(SettingsEditActivity.KEY_NAME, appInfo.name));
}
}
```
--------------------------------
### Discover Android System Settings using Java Reflection
Source: https://context7.com/canyie/settingsfirewall/llms.txt
This Java code dynamically discovers all available Android settings (System, Secure, Global) by inspecting their respective classes using reflection. It identifies settings, handles moved settings, and checks for existing replacements. Dependencies include Android SDK classes like Settings, TextUtils, and reflection APIs.
```java
// App.java - Settings discovery
public static List getSettings(ISettingsFirewall service, int uid) {
Replacement[] replacements;
try {
replacements = service.getReplacements(uid);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
List out = new ArrayList<>();
// Add all Settings.System fields
addSettings(Settings.System.class, out, Replacement.FLAG_SYSTEM, replacements,
"MOVED_TO_SECURE", "MOVED_TO_GLOBAL", "MOVED_TO_SECURE_THEN_GLOBAL");
// Add all Settings.Secure fields
addSettings(Settings.Secure.class, out, Replacement.FLAG_SECURE, replacements,
"MOVED_TO_GLOBAL");
// Add all Settings.Global fields
addSettings(Settings.Global.class, out, Replacement.FLAG_GLOBAL, replacements);
Collections.sort(out, Replacement.COMPARATOR);
return out;
}
private static void addSettings(Class extends Settings.NameValueTable> cls,
List out, int flag,
Replacement[] replacements, String... ignore) {
// Load ignore sets (settings that moved to other namespaces)
Set[] ignoreSets = new Set[ignore.length];
for (int i = 0; i < ignore.length; i++) {
try {
Field field = cls.getDeclaredField(ignore[i]);
field.setAccessible(true);
ignoreSets[i] = (Set) field.get(null);
} catch (Exception e) {
ignoreSets[i] = Collections.emptySet();
}
}
// Iterate all static final String fields
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
int modifiers = field.getModifiers();
if (!(Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers))) continue;
if (field.getType() != String.class) continue;
field.setAccessible(true);
String key;
try {
key = (String) field.get(null);
} catch (Exception e) {
continue;
}
if (TextUtils.isEmpty(key)) continue;
// Skip ignored settings
boolean skip = false;
for (Set set : ignoreSets) {
if (set.contains(key)) {
skip = true;
break;
}
}
if (skip) continue;
// Check if we already have a replacement for this setting
if (replacements != null) {
for (Replacement existing : replacements) {
if (key.equals(existing.key)) {
out.add(existing);
continue;
}
}
}
// Add as unreplaced setting (value = null)
out.add(new Replacement(key, null, flag));
}
}
```
--------------------------------
### Android App Build Configuration (Gradle)
Source: https://context7.com/canyie/settingsfirewall/llms.txt
Configures the Android application build process, including SDK versions, build features like AIDL and BuildConfig, and dependency management for Xposed API and hidden API bypass.
```gradle
// app/build.gradle
plugins {
id 'com.android.application'
}
android {
namespace 'top.canyie.settingsfirewall'
compileSdk 34
defaultConfig {
applicationId "top.canyie.settingsfirewall"
minSdk 18 // Android 4.3+
targetSdk 34
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
buildFeatures {
aidl true // Enable AIDL compilation
buildConfig true
}
}
dependencies {
// Xposed API (compile-only, provided by framework at runtime)
compileOnly 'de.robv.android.xposed:api:82'
// Hidden API access for Android P+ (reflection restrictions bypass)
implementation 'org.lsposed.hiddenapibypass:hiddenapibypass:4.3'
}
```
--------------------------------
### Connect to Firewall Service (Java)
Source: https://context7.com/canyie/settingsfirewall/llms.txt
Demonstrates how to connect to the ISettingsFirewall service from the application UI using Android's ContentResolver. It handles service discovery and retrieves the service binder.
```java
// App.java - Service discovery
public class App extends Application {
private static ISettingsFirewall service;
public static ISettingsFirewall getService(Context context) {
if (service == null) {
// Call Settings Provider with our custom method to get the service binder
Uri uri = Uri.parse("content://" + Settings.AUTHORITY);
try {
Bundle result = context.getContentResolver().call(
uri,
SettingsProviderHook.METHOD, // "GET_SettingsFirewall"
null,
null
);
if (result != null) {
service = ISettingsFirewall.Stub.asInterface(
result.getBinder(Settings.NameValueTable.VALUE)
);
}
} catch (Exception ignored) {
// Service not available - module not activated
}
}
return service;
}
// Load installed apps with firewall status
public static List getSortedList(Context context, ISettingsFirewall service) {
PackageManager pm = context.getPackageManager();
var apps = pm.getInstalledPackages(0);
int[] enabledUids;
try {
enabledUids = service.getTargets();
} catch (RemoteException e) {
throw new RuntimeException(e);
}
Arrays.sort(enabledUids);
List list = new ArrayList<>();
for (var app : apps) {
int uid = app.applicationInfo.uid;
if (uid < Process.SHELL_UID || uid == Process.myUid()) continue;
AppInfo info = new AppInfo();
info.name = app.applicationInfo.loadLabel(pm).toString();
info.icon = app.applicationInfo.loadIcon(pm);
info.uid = uid;
info.enabled = Arrays.binarySearch(enabledUids, uid) >= 0;
list.add(info);
}
Collections.sort(list, AppInfo.COMPARATOR);
return list;
}
}
```
--------------------------------
### Implement Replacement Data Model (Java)
Source: https://context7.com/canyie/settingsfirewall/llms.txt
Implements the Parcelable data class for a setting replacement rule. It includes flags for different settings namespaces and methods for IPC serialization.
```java
// Replacement.java
public final class Replacement implements Serializable, Parcelable {
public static final int FLAG_SYSTEM = 1 << 0; // Settings.System namespace
public static final int FLAG_SECURE = 1 << 1; // Settings.Secure namespace
public static final int FLAG_GLOBAL = 1 << 2; // Settings.Global namespace
public final String key; // Setting name (e.g., "adb_enabled")
public String value; // Replacement value (null = not replaced)
public int flags; // Bitfield of FLAG_* constants
public Replacement(String name, String value, int flags) {
this.key = name;
this.value = value;
this.flags = flags;
}
// Parcelable implementation for IPC
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(key);
dest.writeString(value);
dest.writeInt(this.flags);
}
public static final Creator CREATOR = new Creator<>() {
@Override
public Replacement createFromParcel(Parcel in) {
return new Replacement(in.readString(), in.readString(), in.readInt());
}
@Override
public Replacement[] newArray(int size) {
return new Replacement[size];
}
};
}
```
--------------------------------
### Define IPC Service Interface (AIDL)
Source: https://context7.com/canyie/settingsfirewall/llms.txt
Defines the AIDL interface for cross-process communication between the UI and the system service. It includes methods for managing firewall targets and replacement rules.
```aidl
// ISettingsFirewall.aidl
package top.canyie.settingsfirewall;
import top.canyie.settingsfirewall.Replacement;
interface ISettingsFirewall {
// Get all UIDs with firewall enabled
int[] getTargets() = 1;
// Enable/disable firewall for specific UID
void setTarget(int uid, boolean enabled) = 2;
// Get all replacement rules for a UID
Replacement[] getReplacements(int uid) = 3;
// Set replacement value for a specific setting
void setReplacement(int uid, String setting, String value, int flags) = 4;
// Remove replacement rule
void deleteReplacement(int uid, String setting) = 5;
}
```
--------------------------------
### Java Firewall Policy Management Service
Source: https://context7.com/canyie/settingsfirewall/llms.txt
Implements an IPC service for managing firewall policies. It supports thread-safe operations for loading, retrieving, and setting firewall rules. Dependencies include Android Context, SharedPreferences, File I/O, and Xposed Bridge for logging.
```java
// SettingsFirewallService.java - IPC service for policy management
public class SettingsFirewallService extends ISettingsFirewall.Stub {
public static final SettingsFirewallService INSTANCE = new SettingsFirewallService();
private static final Set targetUids = new HashSet<>();
private static final SparseArray> policyCache = new SparseArray<>();
private static final Lock readLock, writeLock;
static {
var lock = new ReentrantReadWriteLock();
readLock = lock.readLock();
writeLock = lock.writeLock();
}
public static void init(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
context = context.createDeviceProtectedStorageContext();
// Load target UIDs from SharedPreferences
sharedPreferences = context.getSharedPreferences("settings-firewall", Context.MODE_PRIVATE);
var uidSet = sharedPreferences.getStringSet("firewall_targets", null);
if (uidSet != null) {
for (String uid : uidSet) {
targetUids.add(Integer.valueOf(uid));
}
}
// Load replacement policies from serialized files
policyDir = context.getDir("settings-firewall", Context.MODE_PRIVATE);
File[] files = policyDir.listFiles();
for (File file : files) {
int uid = Integer.parseInt(file.getName());
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(file))) {
policyCache.put(uid, (List) in.readObject());
} catch (Exception e) {
XposedBridge.log("Error reading " + file);
}
}
}
// Thread-safe lookup of replacement values
public static String getReplacement(int uid, String setting, int flag) {
readLock.lock();
try {
if (!targetUids.contains(uid)) return null;
List replacements = policyCache.get(uid);
if (replacements != null) {
for (Replacement replacement : replacements) {
if (setting.equals(replacement.key) && (replacement.flags & flag) != 0) {
return replacement.value;
}
}
}
} finally {
readLock.unlock();
}
return null;
}
// Enable/disable firewall for specific UID
@Override
public void setTarget(int uid, boolean enabled) {
writeLock.lock();
try {
if (enabled)
targetUids.add(uid);
else
targetUids.remove(uid);
// Persist to SharedPreferences
Set stringSet = new HashSet<>();
for (Integer u : targetUids) {
stringSet.add(u.toString());
}
sharedPreferences.edit().putStringSet("firewall_targets", stringSet).commit();
} finally {
writeLock.unlock();
}
}
// Add or update replacement rule
@Override
public void setReplacement(int uid, String setting, String value, int flags) {
writeLock.lock();
try {
List replacements = policyCache.get(uid);
if (replacements == null) {
policyCache.put(uid, replacements = new ArrayList<>());
}
// Update existing or add new
boolean found = false;
for (Replacement replacement : replacements) {
if (setting.equals(replacement.key)) {
replacement.value = value;
replacement.flags = flags;
found = true;
break;
}
}
if (!found) {
replacements.add(new Replacement(setting, value, flags));
}
// Persist to file
try (ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream(new File(policyDir, Integer.toString(uid))))) {
out.writeObject(replacements);
} catch (IOException e) {
XposedBridge.log("Error saving rules of uid " + uid);
}
} finally {
writeLock.unlock();
}
}
}
```
--------------------------------
### Hook Scope Configuration (XML)
Source: https://context7.com/canyie/settingsfirewall/llms.txt
Defines the scope of hooks for the firewall module, specifying system components like the Android framework and Settings Provider that the module will intercept.
```xml
- android
- com.android.providers.settings
```
--------------------------------
### Intercept Settings Access with Xposed
Source: https://context7.com/canyie/settingsfirewall/llms.txt
This Java code implements the core Xposed hook for the SettingsFirewall module. It intercepts calls to the `SettingsProvider.call()` method to monitor and control application access to system settings. It requires the Xposed framework and operates on Android 4.3+.
```java
// SettingsProviderHook.java - Main Xposed hook implementation
public class SettingsProviderHook extends XC_MethodHook implements IXposedHookLoadPackage {
public static final String METHOD = "GET_SettingsFirewall";
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
if (!"com.android.providers.settings".equals(lpparam.packageName)) return;
// Hook the SettingsProvider.call() method
XposedHelpers.findAndHookMethod(
"com.android.providers.settings.SettingsProvider",
lpparam.classLoader,
"call",
String.class, // method parameter
String.class, // name parameter
Bundle.class, // args parameter
this
);
}
@Override
protected void beforeHookedMethod(MethodHookParam param) {
ContentProvider contentProvider = (ContentProvider) param.thisObject;
String method = (String) param.args[0];
String name = (String) param.args[1];
int callingUid = Binder.getCallingUid();
// Handle service discovery from our own app
if (METHOD.equals(method)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
&& !BuildConfig.APPLICATION_ID.equals(contentProvider.getCallingPackage())) {
return;
}
param.setResult(SettingsFirewallService.BUNDLE);
return;
}
// Intercept GET operations
int flag;
switch (method) {
case "GET_global":
flag = Replacement.FLAG_GLOBAL;
break;
case "GET_secure":
flag = Replacement.FLAG_SECURE;
break;
case "GET_system":
flag = Replacement.FLAG_SYSTEM;
break;
default:
return;
}
// Check if we have a replacement value for this UID and setting
String replacement = SettingsFirewallService.getReplacement(callingUid, name, flag);
if (replacement != null) {
Bundle result = new Bundle(1);
result.putString(Settings.NameValueTable.VALUE, replacement);
param.setResult(result); // Return fake value instead of real setting
}
}
}
```
--------------------------------
### Edit App Settings Replacement Values - Java
Source: https://context7.com/canyie/settingsfirewall/llms.txt
This Java code snippet details the SettingsEditActivity, responsible for editing individual setting replacement values for a given application. It initializes the service, loads existing settings, and provides UI elements for users to modify or delete replacement values. The activity uses Android AlertDialog for editing and interacts with the ISettingsFirewall service to persist changes. Dependencies include Android Activity, View, AlertDialog, EditText, and the custom ISettingsFirewall service.
```java
public class SettingsEditActivity extends Activity {
private int uid;
private ISettingsFirewall service;
private SettingListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uid = getIntent().getIntExtra(KEY_UID, -1);
service = App.getService(this);
// Load all available settings with current replacement values
List settings = App.getSettings(service, uid);
adapter = new SettingListAdapter(this, settings);
ListView listView = findViewById(R.id.list);
listView.setAdapter(adapter);
}
public void onItemClicked(Replacement replacement) {
var layout = layoutInflater.inflate(R.layout.edit_dialog, null);
EditText editText = layout.findViewById(R.id.edit);
if (replacement.value != null)
editText.setText(replacement.value);
new AlertDialog.Builder(this)
.setTitle(getString(R.string.editing, replacement.key))
.setView(layout)
.setPositiveButton(R.string.save, (dialog, which) -> {
// Save replacement value
replacement.value = editText.getText().toString();
try {
service.setReplacement(uid, replacement.key, replacement.value, replacement.flags);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
adapter.notifyDataSetChanged();
})
.setNeutralButton(R.string.delete, (dialog, which) -> {
// Remove replacement (allow real value through)
replacement.value = null;
try {
service.deleteReplacement(uid, replacement.key);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
adapter.notifyDataSetChanged();
})
.show();
}
}
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.