Enable airplane mode when booting in safe mode

Make it possible to boot in airplane mode when it was not turned on
before shutdown/reboot, either for situations where this is required by
regulation or to work around problems in normal boot. When safe mode is
engaged (Vol-Down), disabled in two stages:
1. Set Settings.Global.AIRPLANE_MODE_ON as early as possible for
   subsystems to react to it during their initialization.
2. Trigger the public ConnectiviyService API to enable airplane mode. This
   has to be done during later stages in initialization because it requires
   sending broadcasts, so some RF leakage may still happen before airplane
   mode is enabled (time window of a few seconds).

Bluetooth is not currently disabled and needs to be fixed by another
change. WiFi and NFC are turned off alongside cellular modems.

Test: manual
Bug: 120145930
Change-Id: I1d61990a9d6f7cd046d28b3e49ecf402dd485063
(cherry picked from commit afc9bc80941ea015cb591a0032e7553b5805fcc6)
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 555e899..5ea3390 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -279,7 +279,7 @@
 
                 Slog.d(TAG,
                         "Airplane Mode change - current state:  " + BluetoothAdapter.nameForState(
-                                st));
+                                st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
 
                 if (isAirplaneModeOn()) {
                     // Clear registered LE apps to force shut-off
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 10d9798..23492a6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -966,6 +966,18 @@
             Slog.e("System", "************ Failure starting core service", e);
         }
 
+        // Before things start rolling, be sure we have decided whether
+        // we are in safe mode.
+        final boolean safeMode = wm.detectSafeMode();
+        if (safeMode) {
+            // If yes, immediately turn on the global setting for airplane mode.
+            // Note that this does not send broadcasts at this stage because
+            // subsystems are not yet up. We will send broadcasts later to ensure
+            // all listeners have the chance to react with special handling.
+            Settings.Global.putInt(context.getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, 1);
+        }
+
         StatusBarManagerService statusBar = null;
         INotificationManager notification = null;
         LocationManagerService location = null;
@@ -1672,9 +1684,6 @@
         mSystemServiceManager.startService(StatsCompanionService.Lifecycle.class);
         traceEnd();
 
-        // Before things start rolling, be sure we have decided whether
-        // we are in safe mode.
-        final boolean safeMode = wm.detectSafeMode();
         if (safeMode) {
             traceBeginAndSlog("EnterSafeModeAndDisableJitCompilation");
             mActivityManagerService.enterSafeMode();
@@ -1862,6 +1871,20 @@
                 reportWtf("starting System UI", e);
             }
             traceEnd();
+            // Enable airplane mode in safe mode. setAirplaneMode() cannot be called
+            // earlier as it sends broadcasts to other services.
+            // TODO: This may actually be too late if radio firmware already started leaking
+            // RF before the respective services start. However, fixing this requires changes
+            // to radio firmware and interfaces.
+            if (safeMode) {
+                traceBeginAndSlog("EnableAirplaneModeInSafeMode");
+                try {
+                    connectivityF.setAirplaneMode(true);
+                } catch (Throwable e) {
+                    reportWtf("enabling Airplane Mode during Safe Mode bootup", e);
+                }
+                traceEnd();
+            }
             traceBeginAndSlog("MakeNetworkManagementServiceReady");
             try {
                 if (networkManagementF != null) networkManagementF.systemReady();