Commit 898b6f85 authored by Mikkel Nygaard Ravn's avatar Mikkel Nygaard Ravn Committed by GitHub

Enable iOS use of platform channels (#8695)

Changed standard encoding to use host endianness. Engine roll.
parent cbb495c1
e0c702e35300b7fdef975b9929df25e112fa9eda
b97103b4415679d893bdcb581f3243c34f4551d4
\ No newline at end of file
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
......
......@@ -6,10 +6,33 @@
#import <Flutter/Flutter.h>
@implementation AppDelegate {
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
@implementation AppDelegate
- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
FlutterViewController* controller =
(FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
methodChannelNamed:@"battery"
binaryMessenger:controller
codec:[FlutterStandardMethodCodec sharedInstance]];
[batteryChannel setMethodCallHandler:^(FlutterMethodCall* call,
FlutterResultReceiver result) {
if ([@"getBatteryLevel" isEqualToString:call.method]) {
UIDevice* device = UIDevice.currentDevice;
device.batteryMonitoringEnabled = YES;
if (device.batteryState == UIDeviceBatteryStateUnknown) {
result(nil, [FlutterError errorWithCode:@"UNAVAILABLE"
message:@"Battery info unavailable"
details:nil]);
} else {
result([NSNumber numberWithInt:(int)(device.batteryLevel * 100)], nil);
}
} else {
result(nil, [FlutterError errorWithCode:@"UNKNOWN_METHOD"
message:@"Unknown battery method called"
details:nil]);
}
}];
return YES;
}
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
......@@ -14,9 +18,9 @@
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
......
......@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
#import "AppDelegate.h"
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
int main(int argc, char * argv[]) {
int main(int argc, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class]));
......
......@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
......@@ -19,16 +18,12 @@ class _PlatformServicesState extends State<PlatformServices> {
Future<Null> _getBatteryLevel() async {
String batteryLevel;
if (Platform.isIOS) {
batteryLevel = "iOS is not supported yet.";
} else {
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}
}
setState(() {
_batteryLevel = batteryLevel;
});
......@@ -45,10 +40,10 @@ class _PlatformServicesState extends State<PlatformServices> {
child: new Text('Get Battery Level'),
onPressed: _getBatteryLevel,
),
new Text(_batteryLevel)
new Text(_batteryLevel),
],
)
)
),
),
);
}
}
......
......@@ -11,8 +11,7 @@ import 'package:typed_data/typed_buffers.dart' show Uint8Buffer;
/// A WriteBuffer instance can be used only once. Attempts to reuse will result
/// in [NoSuchMethodError]s being thrown.
///
/// The byte order of serialized data is [Endianness.BIG_ENDIAN].
/// The byte order of deserialized data is [Endianness.HOST_ENDIAN].
/// The byte order used is [Endianness.HOST_ENDIAN] throughout.
class WriteBuffer {
WriteBuffer() {
_buffer = new Uint8Buffer();
......@@ -28,26 +27,28 @@ class WriteBuffer {
_buffer.add(byte);
}
void putUint16(int value) {
_eightBytes.setUint16(0, value, Endianness.HOST_ENDIAN);
_buffer.addAll(_eightBytesAsList, 0, 2);
}
void putUint32(int value) {
_eightBytes.setUint32(0, value, Endianness.HOST_ENDIAN);
_buffer.addAll(_eightBytesAsList, 0, 4);
}
void putInt32(int value) {
putUint8(value >> 24);
putUint8(value >> 16);
putUint8(value >> 8);
putUint8(value);
_eightBytes.setInt32(0, value, Endianness.HOST_ENDIAN);
_buffer.addAll(_eightBytesAsList, 0, 4);
}
void putInt64(int value) {
putUint8(value >> 56);
putUint8(value >> 48);
putUint8(value >> 40);
putUint8(value >> 32);
putUint8(value >> 24);
putUint8(value >> 16);
putUint8(value >> 8);
putUint8(value);
_eightBytes.setInt64(0, value, Endianness.HOST_ENDIAN);
_buffer.addAll(_eightBytesAsList, 0, 8);
}
void putFloat64(double value) {
_eightBytes.setFloat64(0, value);
_eightBytes.setFloat64(0, value, Endianness.HOST_ENDIAN);
_buffer.addAll(_eightBytesAsList);
}
......@@ -57,32 +58,17 @@ class WriteBuffer {
void putInt32List(Int32List list) {
_alignTo(4);
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length));
} else {
for (final int value in list)
putInt32(value);
}
}
void putInt64List(Int64List list) {
_alignTo(8);
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length));
} else {
for (final int value in list)
putInt64(value);
}
}
void putFloat64List(Float64List list) {
_alignTo(8);
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length));
} else {
for (final double value in list)
putFloat64(value);
}
}
void _alignTo(int alignment) {
......@@ -102,8 +88,7 @@ class WriteBuffer {
/// Read-only buffer for reading sequentially from a [ByteData] instance.
///
/// The byte order of serialized data is [Endianness.BIG_ENDIAN].
/// The byte order of deserialized data is [Endianness.HOST_ENDIAN].
/// The byte order used is [Endianness.HOST_ENDIAN] throughout.
class ReadBuffer {
final ByteData data;
int position = 0;
......@@ -117,20 +102,32 @@ class ReadBuffer {
return data.getUint8(position++);
}
int getUint16() {
final int value = data.getUint16(position, Endianness.HOST_ENDIAN);
position += 2;
return value;
}
int getUint32() {
final int value = data.getUint32(position, Endianness.HOST_ENDIAN);
position += 4;
return value;
}
int getInt32() {
final int value = data.getInt32(position);
final int value = data.getInt32(position, Endianness.HOST_ENDIAN);
position += 4;
return value;
}
int getInt64() {
final int value = data.getInt64(position);
final int value = data.getInt64(position, Endianness.HOST_ENDIAN);
position += 8;
return value;
}
double getFloat64() {
final double value = data.getFloat64(position);
final double value = data.getFloat64(position, Endianness.HOST_ENDIAN);
position += 8;
return value;
}
......@@ -143,45 +140,21 @@ class ReadBuffer {
Int32List getInt32List(int length) {
_alignTo(4);
Int32List list;
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
list = data.buffer.asInt32List(data.offsetInBytes + position, length);
} else {
final ByteData invertedData = new ByteData(4 * length);
for (int i = 0; i < length; i++)
invertedData.setInt32(i * 4, data.getInt32(position + i * 4, Endianness.HOST_ENDIAN));
list = new Int32List.view(invertedData.buffer);
}
final Int32List list = data.buffer.asInt32List(data.offsetInBytes + position, length);
position += 4 * length;
return list;
}
Int64List getInt64List(int length) {
_alignTo(8);
Int64List list;
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
list = data.buffer.asInt64List(data.offsetInBytes + position, length);
} else {
final ByteData invertedData = new ByteData(8 * length);
for (int i = 0; i < length; i++)
invertedData.setInt64(i * 8, data.getInt64(position + i * 8, Endianness.HOST_ENDIAN));
list = new Int64List.view(invertedData.buffer);
}
final Int64List list = data.buffer.asInt64List(data.offsetInBytes + position, length);
position += 8 * length;
return list;
}
Float64List getFloat64List(int length) {
_alignTo(8);
Float64List list;
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
list = data.buffer.asFloat64List(data.offsetInBytes + position, length);
} else {
final ByteData invertedData = new ByteData(8 * length);
for (int i = 0; i < length; i++)
invertedData.setFloat64(i * 8, data.getFloat64(position + i * 8, Endianness.HOST_ENDIAN));
list = new Float64List.view(invertedData.buffer);
}
final Float64List list = data.buffer.asFloat64List(data.offsetInBytes + position, length);
position += 8 * length;
return list;
}
......
......@@ -136,21 +136,20 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
// * A single byte with one of the constant values below determines the
// type of the value.
// * The serialization of the value itself follows the type byte.
// * Numbers are represented using the host endianness throughout.
// * Lengths and sizes of serialized parts are encoded using an expanding
// format optimized for the common case of small non-negative integers:
// * values 0..253 inclusive using one byte with that value;
// * values 254..2^16 inclusive using three bytes, the first of which is
// 254, the next two the usual big-endian unsigned representation of the
// value;
// 254, the next two the usual unsigned representation of the value;
// * values 2^16+1..2^32 inclusive using five bytes, the first of which is
// 255, the next four the usual big-endian unsigned representation of the
// value.
// 255, the next four the usual unsigned representation of the value.
// * null, true, and false have empty serialization; they are encoded directly
// in the type byte (using _kNull, _kTrue, _kFalse)
// * Integers representable in 32 bits are encoded using 4 bytes big-endian,
// two's complement representation.
// * Larger integers representable in 64 bits are encoded using 8 bytes
// big-endian, two's complement representation.
// * Integers representable in 32 bits are encoded using 4 bytes two's
// complement representation.
// * Larger integers representable in 64 bits are encoded using 8 bytes two's
// complement representation.
// * Still larger integers are encoded using their hexadecimal string
// representation. First the length of that is encoded in the expanding
// format, then follows the UTF-8 representation of the hex string.
......@@ -164,8 +163,7 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
// smallest number of zero bytes needed to align the position in the full
// message with a multiple of the number of bytes per element, then the
// encoding of the list elements themselves, end-to-end with no additional
// type information, using big-endian two's complement or IEEE 754 as
// applicable.
// type information, using two's complement or IEEE 754 as applicable.
// * Lists are encoded by first encoding their length in the expanding format,
// then follows the recursive encoding of each element value, including the
// type byte (Lists are assumed to be heterogeneous).
......@@ -215,14 +213,10 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
buffer.putUint8(value);
} else if (value <= 0xffff) {
buffer.putUint8(254);
buffer.putUint8(value >> 8);
buffer.putUint8(value);
buffer.putUint16(value);
} else {
buffer.putUint8(255);
buffer.putUint8(value >> 24);
buffer.putUint8(value >> 16);
buffer.putUint8(value >> 8);
buffer.putUint8(value);
buffer.putUint32(value);
}
}
......@@ -288,17 +282,12 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
static int _readSize(ReadBuffer buffer) {
final int value = buffer.getUint8();
if (value < 254) {
if (value < 254)
return value;
} else if (value == 254) {
return (buffer.getUint8() << 8)
| buffer.getUint8();
} else {
return (buffer.getUint8() << 24)
| (buffer.getUint8() << 16)
| (buffer.getUint8() << 8)
| buffer.getUint8();
}
else if (value == 254)
return buffer.getUint16();
else
return buffer.getUint32();
}
static dynamic _readValue(ReadBuffer buffer) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment