Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b21d225f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add notification for Test Harness Mode"

parents e00f6c33 b5abc2f4
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -3602,6 +3602,11 @@
    <string name="adb_active_notification_message">Tap to turn off USB debugging</string>
    <string name="adb_active_notification_message" product="tv">Select to disable USB debugging.</string>

    <!-- Title of notification shown when Test Harness Mode is enabled. [CHAR LIMIT=NONE] -->
    <string name="test_harness_mode_notification_title">Test Harness Mode enabled</string>
    <!-- Message of notification shown when Test Harness Mode is enabled. [CHAR LIMIT=NONE] -->
    <string name="test_harness_mode_notification_message">Perform a factory reset to disable Test Harness Mode.</string>

    <!-- Title of notification shown when contaminant is detected on the USB port. [CHAR LIMIT=NONE] -->
    <string name="usb_contaminant_detected_title">Liquid or debris in USB port</string>
    <!-- Message of notification shown when contaminant is detected on the USB port. [CHAR LIMIT=NONE] -->
+2 −0
Original line number Diff line number Diff line
@@ -2060,6 +2060,8 @@
  <java-symbol type="string" name="accessibility_binding_label" />
  <java-symbol type="string" name="adb_active_notification_message" />
  <java-symbol type="string" name="adb_active_notification_title" />
  <java-symbol type="string" name="test_harness_mode_notification_title" />
  <java-symbol type="string" name="test_harness_mode_notification_message" />
  <java-symbol type="string" name="taking_remote_bugreport_notification_title" />
  <java-symbol type="string" name="share_remote_bugreport_notification_title" />
  <java-symbol type="string" name="sharing_remote_bugreport_notification_title" />
+4 −0
Original line number Diff line number Diff line
@@ -226,6 +226,10 @@ message SystemMessage {
    // Inform that user that the USB port is free of contaminants.
    NOTE_USB_CONTAMINANT_NOT_DETECTED = 53;

    // Inform the user that Test Harness Mode is active.
    // Package: android
    NOTE_TEST_HARNESS_MODE_ENABLED = 54;

    // ADD_NEW_IDS_ABOVE_THIS_LINE
    // Legacy IDs with arbitrary values appear below
    // Legacy IDs existed as stable non-conflicting constants prior to the O release
+78 −21
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.testharness;

import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -35,6 +37,8 @@ import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;

import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.server.LocalServices;
import com.android.server.PersistentDataBlockManagerInternal;
import com.android.server.SystemService;
@@ -87,6 +91,7 @@ public class TestHarnessModeService extends SystemService {
            case PHASE_BOOT_COMPLETED:
                disableAutoSync();
                configureSettings();
                showNotification();
                break;
        }
        super.onBootPhase(phase);
@@ -99,19 +104,29 @@ public class TestHarnessModeService extends SystemService {
            // There's no data to apply, so leave it as-is.
            return;
        }
        PersistentData persistentData;
        try {
            persistentData = PersistentData.fromBytes(testHarnessModeData);
        } catch (SetUpTestHarnessModeException e) {
            Slog.e(TAG, "Failed to set up Test Harness Mode. Bad data.", e);
            return;
        } finally {
            // Clear out the Test Harness Mode data. It's now in memory if successful or we should
            // skip setting up.
            getPersistentDataBlock().clearTestHarnessModeData();
        }
        mShouldSetUpTestHarnessMode = true;
        setUpAdb(testHarnessModeData);
        setUpAdb(persistentData);
        setDeviceProvisioned();
    }

    private void setUpAdb(byte[] testHarnessModeData) {
    private void setUpAdb(PersistentData persistentData) {
        ContentResolver cr = getContext().getContentResolver();

        // Disable the TTL for ADB keys before enabling ADB
        Settings.Global.putLong(cr, Settings.Global.ADB_ALLOWED_CONNECTION_TIME, 0);

        PersistentData persistentData = PersistentData.fromBytes(testHarnessModeData);

        SystemProperties.set(TEST_HARNESS_MODE_PROPERTY, persistentData.mEnabled ? "1" : "0");
        SystemProperties.set(TEST_HARNESS_MODE_PROPERTY, "1");
        writeAdbKeysFile(persistentData);
    }

@@ -145,9 +160,6 @@ public class TestHarnessModeService extends SystemService {

        writeBytesToFile(persistentData.mAdbKeys, adbManager.getAdbKeysFile().toPath());
        writeBytesToFile(persistentData.mAdbTempKeys, adbManager.getAdbTempKeysFile().toPath());

        // Clear out the data block so that we don't revert the ADB keys on every boot.
        getPersistentDataBlock().clearTestHarnessModeData();
    }

    private void writeBytesToFile(byte[] keys, Path adbKeys) {
@@ -177,6 +189,36 @@ public class TestHarnessModeService extends SystemService {
                UserHandle.USER_CURRENT);
    }

    private void showNotification() {
        if (!SystemProperties.getBoolean(TEST_HARNESS_MODE_PROPERTY, false)) {
            return;
        }
        String title = getContext()
                .getString(com.android.internal.R.string.test_harness_mode_notification_title);
        String message = getContext()
                .getString(com.android.internal.R.string.test_harness_mode_notification_message);

        Notification notification =
                new Notification.Builder(getContext(), SystemNotificationChannels.DEVELOPER)
                        .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                        .setWhen(0)
                        .setOngoing(true)
                        .setTicker(title)
                        .setDefaults(0)  // please be quiet
                        .setColor(getContext().getColor(
                                com.android.internal.R.color
                                        .system_notification_accent_color))
                        .setContentTitle(title)
                        .setContentText(message)
                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                        .build();

        NotificationManager notificationManager =
                getContext().getSystemService(NotificationManager.class);
        notificationManager.notifyAsUser(
                null, SystemMessage.NOTE_TEST_HARNESS_MODE_ENABLED, notification, UserHandle.ALL);
    }

    @Nullable
    private PersistentDataBlockManagerInternal getPersistentDataBlock() {
        if (mPersistentDataBlockManagerInternal == null) {
@@ -248,8 +290,7 @@ public class TestHarnessModeService extends SystemService {
                byte[] adbKeysBytes = getBytesFromFile(adbKeys);
                byte[] adbTempKeysBytes = getBytesFromFile(adbTempKeys);

                PersistentData persistentData =
                        new PersistentData(true, adbKeysBytes, adbTempKeysBytes);
                PersistentData persistentData = new PersistentData(adbKeysBytes, adbTempKeysBytes);
                getPersistentDataBlock().setTestHarnessModeData(persistentData.toBytes());
            } catch (IOException e) {
                Slog.e(TAG, "Failed to store ADB keys.", e);
@@ -316,37 +357,40 @@ public class TestHarnessModeService extends SystemService {
     */
    public static class PersistentData {
        static final byte VERSION_1 = 1;
        static final byte VERSION_2 = 2;

        final int mVersion;
        final boolean mEnabled;
        final byte[] mAdbKeys;
        final byte[] mAdbTempKeys;

        PersistentData(boolean enabled, byte[] adbKeys, byte[] adbTempKeys) {
            this(VERSION_1, enabled, adbKeys, adbTempKeys);
        PersistentData(byte[] adbKeys, byte[] adbTempKeys) {
            this(VERSION_2, adbKeys, adbTempKeys);
        }

        PersistentData(int version, boolean enabled, byte[] adbKeys, byte[] adbTempKeys) {
        PersistentData(int version, byte[] adbKeys, byte[] adbTempKeys) {
            this.mVersion = version;
            this.mEnabled = enabled;
            this.mAdbKeys = adbKeys;
            this.mAdbTempKeys = adbTempKeys;
        }

        static PersistentData fromBytes(byte[] bytes) {
        static PersistentData fromBytes(byte[] bytes) throws SetUpTestHarnessModeException {
            try {
                DataInputStream is = new DataInputStream(new ByteArrayInputStream(bytes));
                int version = is.readInt();
                boolean enabled = is.readBoolean();
                if (version == VERSION_1) {
                    // Version 1 of Test Harness Mode contained an "enabled" bit that we need to
                    // skip. If we don't, the binary format will be bad and it will fail to set up.
                    is.readBoolean();
                }
                int adbKeysLength = is.readInt();
                byte[] adbKeys = new byte[adbKeysLength];
                is.readFully(adbKeys);
                int adbTempKeysLength = is.readInt();
                byte[] adbTempKeys = new byte[adbTempKeysLength];
                is.readFully(adbTempKeys);
                return new PersistentData(version, enabled, adbKeys, adbTempKeys);
                return new PersistentData(version, adbKeys, adbTempKeys);
            } catch (IOException e) {
                throw new RuntimeException(e);
                throw new SetUpTestHarnessModeException(e);
            }
        }

@@ -354,8 +398,7 @@ public class TestHarnessModeService extends SystemService {
            try {
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                DataOutputStream dos = new DataOutputStream(os);
                dos.writeInt(VERSION_1);
                dos.writeBoolean(mEnabled);
                dos.writeInt(VERSION_2);
                dos.writeInt(mAdbKeys.length);
                dos.write(mAdbKeys);
                dos.writeInt(mAdbTempKeys.length);
@@ -367,4 +410,18 @@ public class TestHarnessModeService extends SystemService {
            }
        }
    }

    /**
     * An exception thrown when Test Harness Mode fails to set up.
     *
     * <p>In the event that Test Harness Mode fails to set up, all of the data should be discarded
     * and the Test Harness Mode portion of the persistent data block should be wiped. This will
     * prevent the device from becoming stuck, as there is no way (without rooting the device) to
     * clear the persistent data block.
     */
    private static class SetUpTestHarnessModeException extends Exception {
        SetUpTestHarnessModeException(Exception e) {
            super(e);
        }
    }
}