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

Commit 9bb1670c authored by Anthony Stange's avatar Anthony Stange
Browse files

Support REPLAY_DATA_INJECTION mode

For test builds only, allow an app to inject sensor data and have that
data forwarded to all active clients of the sensors framework. This
allows replay frameworks to be built for advanced testing of system
behavior.

Bug: 262573975
Test: Run on prod/test builds and verify it only works on the latter
Test: Verify all modes continue to work as expected
Change-Id: I9e9fcb76cbd7ab4bc8eddffc71d60981f50517f4
parent 3a0ced4b
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -850,6 +850,11 @@ int SensorService::SensorEventConnection::handleEvent(int fd, int events, void*
                    // Unregister call backs.
                    // Unregister call backs.
                    return 0;
                    return 0;
                }
                }
                if (!mService->isWhiteListedPackage(mPackageName)) {
                    ALOGE("App not allowed to inject data, dropping event"
                          "package=%s uid=%d", mPackageName.string(), mUid);
                    return 0;
                }
                sensors_event_t sensor_event;
                sensors_event_t sensor_event;
                memcpy(&sensor_event, buf, sizeof(sensors_event_t));
                memcpy(&sensor_event, buf, sizeof(sensors_event_t));
                std::shared_ptr<SensorInterface> si =
                std::shared_ptr<SensorInterface> si =
+44 −7
Original line number Original line Diff line number Diff line
@@ -52,6 +52,7 @@
#include "SensorEventConnection.h"
#include "SensorEventConnection.h"
#include "SensorRecord.h"
#include "SensorRecord.h"
#include "SensorRegistrationInfo.h"
#include "SensorRegistrationInfo.h"
#include "SensorServiceUtils.h"


#include <inttypes.h>
#include <inttypes.h>
#include <math.h>
#include <math.h>
@@ -571,7 +572,11 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) {
                // enable sensors and recover all sensor direct report
                // enable sensors and recover all sensor direct report
                enableAllSensorsLocked(&connLock);
                enableAllSensorsLocked(&connLock);
            }
            }
            if (mCurrentOperatingMode == DATA_INJECTION) {
            if (mCurrentOperatingMode == REPLAY_DATA_INJECTION) {
                dev.disableAllSensors();
            }
            if (mCurrentOperatingMode == DATA_INJECTION ||
                    mCurrentOperatingMode == REPLAY_DATA_INJECTION) {
               resetToNormalModeLocked();
               resetToNormalModeLocked();
            }
            }
            mWhiteListedPackage.clear();
            mWhiteListedPackage.clear();
@@ -595,6 +600,27 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) {
                // Transition to data injection mode supported only from NORMAL mode.
                // Transition to data injection mode supported only from NORMAL mode.
                return INVALID_OPERATION;
                return INVALID_OPERATION;
            }
            }
        } else if (args.size() == 2 && args[0] == String16("replay_data_injection")
                   && !SensorServiceUtil::isUserBuild()) {
            if (mCurrentOperatingMode == NORMAL) {
                dev.disableAllSensors();
                // Use DATA_INJECTION here since this value goes to the HAL and the HAL doesn't
                // have an understanding of replay vs. normal data injection.
                status_t err = dev.setMode(DATA_INJECTION);
                if (err == NO_ERROR) {
                    mCurrentOperatingMode = REPLAY_DATA_INJECTION;
                }
                // Re-enable sensors.
                dev.enableAllSensors();
                mWhiteListedPackage.setTo(String8(args[1]));
                return NO_ERROR;
            } else if (mCurrentOperatingMode == REPLAY_DATA_INJECTION) {
                // Already in REPLAY_DATA_INJECTION mode. Treat this as a no_op.
                return NO_ERROR;
            } else {
                // Transition to data injection mode supported only from NORMAL mode.
                return INVALID_OPERATION;
            }
        } else if (args.size() == 1 && args[0] == String16("--proto")) {
        } else if (args.size() == 1 && args[0] == String16("--proto")) {
            return dumpProtoLocked(fd, &connLock);
            return dumpProtoLocked(fd, &connLock);
        } else if (!mSensors.hasAnySensor()) {
        } else if (!mSensors.hasAnySensor()) {
@@ -658,6 +684,14 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) {
                   break;
                   break;
               case DATA_INJECTION:
               case DATA_INJECTION:
                   result.appendFormat(" DATA_INJECTION : %s\n", mWhiteListedPackage.string());
                   result.appendFormat(" DATA_INJECTION : %s\n", mWhiteListedPackage.string());
                   break;
               case REPLAY_DATA_INJECTION:
                   result.appendFormat(" REPLAY_DATA_INJECTION : %s\n",
                            mWhiteListedPackage.string());
                   break;
               default:
                   result.appendFormat(" UNKNOWN\n");
                   break;
            }
            }
            result.appendFormat("Sensor Privacy: %s\n",
            result.appendFormat("Sensor Privacy: %s\n",
                    mSensorPrivacyPolicy->isSensorPrivacyEnabled() ? "enabled" : "disabled");
                    mSensorPrivacyPolicy->isSensorPrivacyEnabled() ? "enabled" : "disabled");
@@ -1498,8 +1532,10 @@ Vector<Sensor> SensorService::getRuntimeSensorList(const String16& opPackageName


sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName,
sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName,
        int requestedMode, const String16& opPackageName, const String16& attributionTag) {
        int requestedMode, const String16& opPackageName, const String16& attributionTag) {
    // Only 2 modes supported for a SensorEventConnection ... NORMAL and DATA_INJECTION.
    // Only 3 modes supported for a SensorEventConnection ... NORMAL, DATA_INJECTION and
    if (requestedMode != NORMAL && requestedMode != DATA_INJECTION) {
    // REPLAY_DATA_INJECTION.
    if (requestedMode != NORMAL && requestedMode != DATA_INJECTION &&
            requestedMode != REPLAY_DATA_INJECTION) {
        return nullptr;
        return nullptr;
    }
    }
    resetTargetSdkVersionCache(opPackageName);
    resetTargetSdkVersionCache(opPackageName);
@@ -1520,8 +1556,9 @@ sp<ISensorEventConnection> SensorService::createSensorEventConnection(const Stri
    String16 connOpPackageName =
    String16 connOpPackageName =
            (opPackageName == String16("")) ? String16(connPackageName) : opPackageName;
            (opPackageName == String16("")) ? String16(connPackageName) : opPackageName;
    sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
    sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
            requestedMode == DATA_INJECTION, connOpPackageName, attributionTag));
            requestedMode == DATA_INJECTION || requestedMode == REPLAY_DATA_INJECTION,
    if (requestedMode == DATA_INJECTION) {
            connOpPackageName, attributionTag));
    if (requestedMode == DATA_INJECTION || requestedMode == REPLAY_DATA_INJECTION) {
        mConnectionHolder.addEventConnectionIfNotPresent(result);
        mConnectionHolder.addEventConnectionIfNotPresent(result);
        // Add the associated file descriptor to the Looper for polling whenever there is data to
        // Add the associated file descriptor to the Looper for polling whenever there is data to
        // be injected.
        // be injected.
@@ -1880,8 +1917,8 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
    }
    }


    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
    if (mCurrentOperatingMode != NORMAL
    if (mCurrentOperatingMode != NORMAL && mCurrentOperatingMode != REPLAY_DATA_INJECTION &&
           && !isWhiteListedPackage(connection->getPackageName())) {
           !isWhiteListedPackage(connection->getPackageName())) {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }


+7 −4
Original line number Original line Diff line number Diff line
@@ -102,8 +102,7 @@ public:
       // Step Detector etc. Typically in this mode, there will be a client (a
       // Step Detector etc. Typically in this mode, there will be a client (a
       // SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps can
       // SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps can
       // unregister and register for any sensor that supports injection. Registering to sensors
       // unregister and register for any sensor that supports injection. Registering to sensors
       // that do not support injection will give an error.  TODO: Allow exactly one
       // that do not support injection will give an error.
       // client to inject sensor data at a time.
       DATA_INJECTION = 1,
       DATA_INJECTION = 1,
       // This mode is used only for testing sensors. Each sensor can be tested in isolation with
       // This mode is used only for testing sensors. Each sensor can be tested in isolation with
       // the required sampling_rate and maxReportLatency parameters without having to think about
       // the required sampling_rate and maxReportLatency parameters without having to think about
@@ -116,10 +115,14 @@ public:
       // corresponding parameters if the application hasn't unregistered for sensors in the mean
       // corresponding parameters if the application hasn't unregistered for sensors in the mean
       // time.  NOTE: Non allowlisted app whose sensors were previously deactivated may still
       // time.  NOTE: Non allowlisted app whose sensors were previously deactivated may still
       // receive events if a allowlisted app requests data from the same sensor.
       // receive events if a allowlisted app requests data from the same sensor.
       RESTRICTED = 2
       RESTRICTED = 2,
       // Mostly equivalent to DATA_INJECTION with the difference being that the injected data is
       // delivered to all requesting apps rather than just the package allowed to inject data.
       // This mode is only allowed to be used on development builds.
       REPLAY_DATA_INJECTION = 3,


      // State Transitions supported.
      // State Transitions supported.
      //     RESTRICTED   <---  NORMAL   ---> DATA_INJECTION
      //     RESTRICTED   <---  NORMAL   ---> DATA_INJECTION/REPLAY_DATA_INJECTION
      //                  --->           <---
      //                  --->           <---


      // Shell commands to switch modes in SensorService.
      // Shell commands to switch modes in SensorService.
+6 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


#include "SensorServiceUtils.h"
#include "SensorServiceUtils.h"


#include <android-base/properties.h>
#include <hardware/sensors.h>
#include <hardware/sensors.h>


namespace android {
namespace android {
@@ -76,5 +77,10 @@ size_t eventSizeBySensorType(int type) {
    }
    }
}
}


bool isUserBuild() {
    std::string buildType = android::base::GetProperty("ro.build.type", "user");
    return "user" == buildType;
}

} // namespace SensorServiceUtil
} // namespace SensorServiceUtil
} // namespace android;
} // namespace android;
+5 −0
Original line number Original line Diff line number Diff line
@@ -38,6 +38,11 @@ public:


size_t eventSizeBySensorType(int type);
size_t eventSizeBySensorType(int type);


/**
 * Returns true if on a user (production) build.
 */
bool isUserBuild();

} // namespace SensorServiceUtil
} // namespace SensorServiceUtil
} // namespace android;
} // namespace android;