Android Q入力イベント関連表示装置
50990 ワード
イベント関連表示デバイスの入力
inputeventのdisplayIdはどうやって来ましたか?この記事ではdisplayidとInputeventの関係を紹介します.DisplayはDisplayManagerServiceが管理しています.DMSから始めます.
管理サービスの表示(DisplayManagerService)画面が追加されるとDMSはMSGを送信します.REQUEST_TRAVERSALのHandleメッセージ.このメッセージは、DMSが保有するWMSのローカルサービスを介して、WMSのrequestTraversal()を呼び出すことを意味する. WMSウィンドウを巡回するとDMSのperformTraversalInternalメソッドが呼び出され、WMSのapplySurfaceChangesTransaction()メソッドによって呼び出されます. DMSは、viewportを含む各デバイスの情報を構成する.詳しくはconfigureDisplayLocked()、populateViewportLocked()を参照してください. DMSはMSGを送信します.UPDATE_VIEWPORTメッセージはviewportを設定し、performTraversalLocked()を参照してください. IMSのローカルサービスは、これらのviewport情報をJNI層に伝達する. 最終nativeレイヤは、viewport情報をグローバルInputReader Configurationに保存する構成をリフレッシュします.詳細はrequestRefreshConfiguration()を参照してください.
初期化時のプロファイルの解析
このプロファイルは、idcの下に配置され、デバイス名で命名されたidcファイルです.
オフィシャルゲートプロファイルを解析するタイミング. プロファイルを具体的に解析する機能関数 odm、vendor、Systemからファイルが保存されているかどうかを検索します.
入力ポートと表示ポートの構成
構成をリフレッシュすると同時に携帯電話のディレクトリ/etc/input-port-associationsを読み取る.xmlの内容で、このファイルは入力ポートと表示ポートの関連関係を構成します.
コードの詳細はIMSのgetInputPortAssociations()を参照してください.
Googleドキュメントの紹介
プロファイル解析動作
表示ポートの割り当て
ViewPort検索
ビューポートの検索は、表示ポート、一意の表示ID、表示ポートタイプの3つの側面から検索されます.これらが見つからない場合、displayidは-1、viewtypeはVIEWPORT_を作成します.INTERNALのnewViewポート.
inputeventのdisplayIdはどうやって来ましたか?この記事ではdisplayidとInputeventの関係を紹介します.DisplayはDisplayManagerServiceが管理しています.DMSから始めます.
管理サービスの表示(DisplayManagerService)
// Update the corresponding viewport.
if ((info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
viewportType = VIEWPORT_INTERNAL;
} else if (info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
viewportType = VIEWPORT_EXTERNAL;
} else if (info.touch == DisplayDeviceInfo.TOUCH_VIRTUAL
&& !TextUtils.isEmpty(info.uniqueId)) {
viewportType = VIEWPORT_VIRTUAL;
} else {
Slog.i(TAG, "Display " + info + " does not support input device matching.");
return;
}
// ViewPort device uniqueId, event displayID。
private void populateViewportLocked(int viewportType, int displayId, DisplayDevice device, String uniqueId) {
final DisplayViewport viewport = getViewportLocked(viewportType, uniqueId);
device.populateViewportLocked(viewport);
viewport.valid = true;
viewport.displayId = displayId;// Displayid.
}
public final void populateViewportLocked(DisplayViewport viewport) {
viewport.orientation = mCurrentOrientation;
if (mCurrentLayerStackRect != null) {
viewport.logicalFrame.set(mCurrentLayerStackRect);
} else {
viewport.logicalFrame.setEmpty();
}
if (mCurrentDisplayRect != null) {
viewport.physicalFrame.set(mCurrentDisplayRect);
} else {
viewport.physicalFrame.setEmpty();
}
boolean isRotated = (mCurrentOrientation == Surface.ROTATION_90
|| mCurrentOrientation == Surface.ROTATION_270);
DisplayDeviceInfo info = getDisplayDeviceInfoLocked();
viewport.deviceWidth = isRotated ? info.height : info.width;
viewport.deviceHeight = isRotated ? info.width : info.height;
viewport.uniqueId = info.uniqueId;
if (info.address instanceof DisplayAddress.Physical) {
viewport.physicalPort = ((DisplayAddress.Physical) info.address).getPort();
} else {
viewport.physicalPort = null;
}
}
初期化時のプロファイルの解析
このプロファイルは、idcの下に配置され、デバイス名で命名されたidcファイルです.
オフィシャルゲート
// frameworks/native/services/inputflinger/EventHub.cpp
status_t EventHub::openDeviceLocked(const char* devicePath) {
... ...
Device* device = new Device(fd, deviceId, devicePath, identifier);
// Load the configuration file for the device.
loadConfigurationLocked(device);
// Determine whether the device is external or internal.
if (isExternalDeviceLocked(device)) {
device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
}
... ...
}
void EventHub::loadConfigurationLocked(Device* device) {
//
device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
if (device->configurationFile.empty()) {
ALOGD("No input device configuration file found for device '%s'.",
device->identifier.name.c_str());
} else {
// configuration。
status_t status = PropertyMap::load(String8(device->configurationFile.c_str()),
&device->configuration);
if (status) {
ALOGE("Error loading input device configuration file for device '%s'. "
"Using default configuration.",
device->identifier.name.c_str());
}
}
}
std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
const InputDeviceIdentifier& deviceIdentifier,
InputDeviceConfigurationFileType type) {
if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
if (deviceIdentifier.version != 0) {
// Try vendor product version.
std::string versionPath = getInputDeviceConfigurationFilePathByName(
StringPrintf("Vendor_%04x_Product_%04x_Version_%04x",
deviceIdentifier.vendor, deviceIdentifier.product,
deviceIdentifier.version),
type);
if (!versionPath.empty()) {
return versionPath;
}
}
// Try vendor product.
std::string productPath = getInputDeviceConfigurationFilePathByName(
StringPrintf("Vendor_%04x_Product_%04x",
deviceIdentifier.vendor, deviceIdentifier.product),
type);
if (!productPath.empty()) {
return productPath;
}
}
// Try device name.
return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName(), type);
}
std::string getInputDeviceConfigurationFilePathByName(
const std::string& name, InputDeviceConfigurationFileType type) {
// Search system repository.
std::string path;
// Treblized input device config files will be located /odm/usr or /vendor/usr.
const char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")};
for (size_t i = 0; i < size(rootsForPartition); i++) {
if (rootsForPartition[i] == nullptr) {
continue;
}
path = rootsForPartition[i];
path += "/usr/";
appendInputDeviceConfigurationFileRelativePath(path, name, type);
if (!access(path.c_str(), R_OK)) {
return path;
}
}
// Search user repository.
// TODO Should only look here if not in safe mode.
path = "";
char *androidData = getenv("ANDROID_DATA");
if (androidData != nullptr) {
path += androidData;
}
path += "/system/devices/";
appendInputDeviceConfigurationFileRelativePath(path, name, type);
if (!access(path.c_str(), R_OK)) {
return path;
}
// Not found.
return "";
}
入力ポートと表示ポートの構成
構成をリフレッシュすると同時に携帯電話のディレクトリ/etc/input-port-associationsを読み取る.xmlの内容で、このファイルは入力ポートと表示ポートの関連関係を構成します.
コードの詳細はIMSのgetInputPortAssociations()を参照してください.
// Associations between input ports and display ports
// The java method packs the information in the following manner:
// Original data: [{'inputPort1': '1'}, {'inputPort2': '2'}]
// Received data: ['inputPort1', '1', 'inputPort2', '2']
<ports>
<port display="0" input="usb-xhci-hcd.0.auto-1.1/input0" />
<port display="1" input="usb-xhci-hcd.0.auto-1.2/input0" />
ports>
Googleドキュメントの紹介
プロファイル解析動作
// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outConfig) {
... ...
outConfig->portAssociations.clear();
//Java input-port-associations.xml
jobjectArray portAssociations = jobjectArray(env->CallStaticObjectMethod(
gServiceClassInfo.clazz, gServiceClassInfo.getInputPortAssociations));
if (!checkAndClearExceptionFromCallback(env, "getInputPortAssociations") && portAssociations) {
jsize length = env->GetArrayLength(portAssociations);
for (jsize i = 0; i < length / 2; i++) {
std::string inputPort = getStringElementFromJavaArray(env, portAssociations, 2 * i);
std::string displayPortStr =
getStringElementFromJavaArray(env, portAssociations, 2 * i + 1);
uint8_t displayPort;
// Should already have been validated earlier, but do it here for safety.
bool success = ParseUint(displayPortStr, &displayPort);
if (!success) {
ALOGE("Could not parse entry in port configuration file, received: %s",
displayPortStr.c_str());
continue;
}
outConfig->portAssociations.insert({inputPort, displayPort});// 。
}
env->DeleteLocalRef(portAssociations);
}
... ...
}
表示ポートの割り当て
void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
... ...
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
// In most situations, no port will be specified.
mAssociatedDisplayPort = std::nullopt;
// Find the display port that corresponds to the current input port.
const std::string& inputPort = mIdentifier.location;
if (!inputPort.empty()) {
const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
const auto& displayPort = ports.find(inputPort);
if (displayPort != ports.end()) {
mAssociatedDisplayPort = std::make_optional(displayPort->second);
}
}
}
... ...
}
ViewPort検索
ビューポートの検索は、表示ポート、一意の表示ID、表示ポートタイプの3つの側面から検索されます.これらが見つからない場合、displayidは-1、viewtypeはVIEWPORT_を作成します.INTERNALのnewViewポート.
/**
* Determine which DisplayViewport to use.
* 1. If display port is specified, return the matching viewport. If matching viewport not
* found, then return.
* 2. If a device has associated display, get the matching viewport by either unique id or by
* the display type (internal or external).
* 3. Otherwise, use a non-display viewport.
*/
std::optional<DisplayViewport> TouchInputMapper::findViewport() {
if (mParameters.hasAssociatedDisplay) {
const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
if (displayPort) {
// Find the viewport that contains the same port
std::optional<DisplayViewport> v = mConfig.getDisplayViewportByPort(*displayPort);
if (!v) {
ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
"but the corresponding viewport is not found.",
getDeviceName().c_str(), *displayPort);
}
return v;
}
if (!mParameters.uniqueDisplayId.empty()) {
return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
}
ViewportType viewportTypeToUse;
if (mParameters.associatedDisplayIsExternal) {
viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
} else {
viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
}
std::optional<DisplayViewport> viewport =
mConfig.getDisplayViewportByType(viewportTypeToUse);
if (!viewport && viewportTypeToUse == ViewportType::VIEWPORT_EXTERNAL) {
ALOGW("Input device %s should be associated with external display, "
"fallback to internal one for the external viewport is not found.",
getDeviceName().c_str());
viewport = mConfig.getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
}
return viewport;
}
DisplayViewport newViewport;
// Raw width and height in the natural orientation.
int32_t rawWidth = mRawPointerAxes.getRawWidth();
int32_t rawHeight = mRawPointerAxes.getRawHeight();
newViewport.setNonDisplayViewport(rawWidth, rawHeight);
return std::make_optional(newViewport);
}