mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 13:07:49 +01:00
phone_focus_mode is built for a rooted phone: the hosts layer is a read-only
bind mount over /system/etc/hosts, chosen so that even root-in-a-terminal
cannot overwrite it. None of that ports to a stock locked device. This splits
out the parts that are device-independent so one policy can drive both.
python_pkg/focus_policy parses config.sh rather than copying it, so the shell
config stays the source of truth and the two cannot drift. It rejects the
shipped REDACTED_* coordinate placeholder instead of defaulting to (0,0),
which would move "home" to the Atlantic and quietly disable the location gate.
blocklist.py converts the hosts file to domains for a DoT resolver or a local
VpnService. Three properties of the real 194k-line file make the obvious parser
wrong, and all three are handled: generate_hosts_file.sh *comments out*
deliberate unblocks rather than deleting them, so stripping '#' re-blocks
facebook/messenger/linkedin/4chan; the StevenBlack header carries loopback and
IPv6 housekeeping that would blackhole localhost; and ~1060 upstream annotation
tokens ('#[adware.zeno]', '"spam') render as address=/"spam/, which makes
dnsmasq refuse to start -- taking DNS down rather than blocking anything.
Verified with dnsmasq --test over all 185681 generated domains.
strip_workout_hosts.py had the same class of bug on the live rooted phone:
exact set membership meant the allowlisted googlevideo.com never matched the
dynamic r*---sn-*.googlevideo.com hosts YouTube actually streams from, so the
workout unblock was only partly working. Now suffix-matched (17 lines stripped,
was 14). The three new tests were checked against the original code in a
throwaway worktree; two of them fail there, so they pin the fix rather than
passing vacuously.
focus_owner is a device-owner app that deliberately does nothing yet. It ships
clearDeviceOwnerApp() implemented and tested first, because dpm
remove-active-admin does not work on a device owner: an app that locks the
device down before proving it can let go leaves a soft-brick recoverable only
through fastboot on a locked bootloader. Built, installed and launched on the
Pixel 6a; dumpsys afterwards confirms Device Owner Type -1 and no user
restrictions, i.e. the phone is unchanged.
Measured while scoping this, and not yet reflected in any enforcement code:
on Android 16 both pm suspend and pm disable-user are cleared by a reboot, so
shell-level app blocking is per-session only. setApplicationHidden is assumed
to persist under Device Owner but is untested.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AwepyL5Lxs5QKbKkMpxxxL
62 lines
2.0 KiB
Dart
62 lines
2.0 KiB
Dart
import 'package:flutter/services.dart';
|
|
|
|
/// Provisioning state reported by the native side.
|
|
class DevicePolicyStatus {
|
|
const DevicePolicyStatus({
|
|
required this.packageName,
|
|
required this.isDeviceOwner,
|
|
required this.isAdminActive,
|
|
required this.sdkInt,
|
|
required this.restrictionsApplied,
|
|
});
|
|
|
|
/// Builds a status from the raw platform-channel map.
|
|
factory DevicePolicyStatus.fromMap(Map<Object?, Object?> map) {
|
|
return DevicePolicyStatus(
|
|
packageName: map['packageName']! as String,
|
|
isDeviceOwner: map['isDeviceOwner']! as bool,
|
|
isAdminActive: map['isAdminActive']! as bool,
|
|
sdkInt: map['sdkInt']! as int,
|
|
restrictionsApplied: map['restrictionsApplied']! as bool,
|
|
);
|
|
}
|
|
|
|
final String packageName;
|
|
final bool isDeviceOwner;
|
|
final bool isAdminActive;
|
|
final int sdkInt;
|
|
|
|
/// Whether any user restriction is currently enforced.
|
|
///
|
|
/// Always false in this build: the app is provisioning-capable but inert
|
|
/// until the release path has been verified on a real device.
|
|
final bool restrictionsApplied;
|
|
}
|
|
|
|
/// Dart side of the device-policy platform channel.
|
|
class DevicePolicy {
|
|
const DevicePolicy([this.channel = _defaultChannel]);
|
|
|
|
static const MethodChannel _defaultChannel =
|
|
MethodChannel('com.kuhy.focus_owner/device_policy');
|
|
|
|
final MethodChannel channel;
|
|
|
|
/// Reads the current provisioning state.
|
|
Future<DevicePolicyStatus> status() async {
|
|
final result =
|
|
await channel.invokeMethod<Map<Object?, Object?>>('status');
|
|
return DevicePolicyStatus.fromMap(result!);
|
|
}
|
|
|
|
/// Relinquishes device ownership without wiping the device.
|
|
///
|
|
/// This is the escape hatch. It is deliberately reachable from the app's
|
|
/// main screen with no PC attached, because the situation it exists for is
|
|
/// one where ADB may already be disallowed.
|
|
Future<bool> releaseDeviceOwner() async {
|
|
final released = await channel.invokeMethod<bool>('releaseDeviceOwner');
|
|
return released ?? false;
|
|
}
|
|
}
|