-
Notifications
You must be signed in to change notification settings - Fork 6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reland No.2 "Hardware Keyboard: Android" (#33686)
* Original code * Changes * Fix and test Better formatted tests
- Loading branch information
Showing
16 changed files
with
3,166 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 140 additions & 0 deletions
140
shell/platform/android/io/flutter/embedding/android/KeyData.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package io.flutter.embedding.android; | ||
|
||
import androidx.annotation.NonNull; | ||
import androidx.annotation.Nullable; | ||
import java.io.UnsupportedEncodingException; | ||
import java.nio.ByteBuffer; | ||
import java.nio.ByteOrder; | ||
|
||
/** | ||
* The resulting Flutter key events generated by {@link KeyEmbedderResponder}, and are sent through | ||
* the messenger after being marshalled with {@link #toBytes()}. | ||
* | ||
* <p>This class is the Java adaption of {@code KeyData} and {@code KeyDataPacket} in the C engine. | ||
* Changes made to either side must also be made to the other. | ||
* | ||
* <p>Each {@link KeyData} corresponds to a {@code ui.KeyData} in the framework. | ||
*/ | ||
public class KeyData { | ||
private static final String TAG = "KeyData"; | ||
|
||
/** | ||
* The channel that key data should be sent through. | ||
* | ||
* <p>Must be kept in sync with kFlutterKeyDataChannel in embedder.cc | ||
*/ | ||
public static final String CHANNEL = "flutter/keydata"; | ||
|
||
// The number of fields except for `character`. | ||
private static final int FIELD_COUNT = 5; | ||
private static final int BYTES_PER_FIELD = 8; | ||
|
||
/** The action type of the key data. */ | ||
public enum Type { | ||
kDown(0), | ||
kUp(1), | ||
kRepeat(2); | ||
|
||
private long value; | ||
|
||
private Type(long value) { | ||
this.value = value; | ||
} | ||
|
||
public long getValue() { | ||
return value; | ||
} | ||
|
||
static Type fromLong(long value) { | ||
switch ((int) value) { | ||
case 0: | ||
return kDown; | ||
case 1: | ||
return kUp; | ||
case 2: | ||
return kRepeat; | ||
default: | ||
throw new AssertionError("Unexpected Type value"); | ||
} | ||
} | ||
} | ||
|
||
/** Creates an empty {@link KeyData}. */ | ||
public KeyData() {} | ||
|
||
/** | ||
* Unmarshal fields from a buffer. | ||
* | ||
* <p>For the binary format, see {@code lib/ui/window/key_data_packet.h}. | ||
*/ | ||
public KeyData(@NonNull ByteBuffer buffer) { | ||
final long charSize = buffer.getLong(); | ||
this.timestamp = buffer.getLong(); | ||
this.type = Type.fromLong(buffer.getLong()); | ||
this.physicalKey = buffer.getLong(); | ||
this.logicalKey = buffer.getLong(); | ||
this.synthesized = buffer.getLong() != 0; | ||
|
||
if (buffer.remaining() != charSize) { | ||
throw new AssertionError( | ||
String.format( | ||
"Unexpected char length: charSize is %d while buffer has position %d, capacity %d, limit %d", | ||
charSize, buffer.position(), buffer.capacity(), buffer.limit())); | ||
} | ||
this.character = null; | ||
if (charSize != 0) { | ||
final byte[] strBytes = new byte[(int) charSize]; | ||
buffer.get(strBytes, 0, (int) charSize); | ||
try { | ||
this.character = new String(strBytes, "UTF-8"); | ||
} catch (UnsupportedEncodingException e) { | ||
throw new AssertionError("UTF-8 unsupported"); | ||
} | ||
} | ||
} | ||
|
||
long timestamp; | ||
Type type; | ||
long physicalKey; | ||
long logicalKey; | ||
boolean synthesized; | ||
|
||
/** The character of this key data encoded in UTF-8. */ | ||
@Nullable String character; | ||
|
||
/** | ||
* Marshal the key data to a new byte buffer. | ||
* | ||
* <p>For the binary format, see {@code lib/ui/window/key_data_packet.h}. | ||
* | ||
* @return the marshalled bytes. | ||
*/ | ||
ByteBuffer toBytes() { | ||
byte[] charBytes; | ||
try { | ||
charBytes = character == null ? null : character.getBytes("UTF-8"); | ||
} catch (UnsupportedEncodingException e) { | ||
throw new AssertionError("UTF-8 not supported"); | ||
} | ||
final int charSize = charBytes == null ? 0 : charBytes.length; | ||
final ByteBuffer packet = | ||
ByteBuffer.allocateDirect((1 + FIELD_COUNT) * BYTES_PER_FIELD + charSize); | ||
packet.order(ByteOrder.LITTLE_ENDIAN); | ||
|
||
packet.putLong(charSize); | ||
packet.putLong(timestamp); | ||
packet.putLong(type.getValue()); | ||
packet.putLong(physicalKey); | ||
packet.putLong(logicalKey); | ||
packet.putLong(synthesized ? 1L : 0L); | ||
if (charBytes != null) { | ||
packet.put(charBytes); | ||
} | ||
|
||
return packet; | ||
} | ||
} |
Oops, something went wrong.