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 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h> #import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate @interface AppDelegate : FlutterAppDelegate
......
...@@ -6,10 +6,33 @@ ...@@ -6,10 +6,33 @@
#import <Flutter/Flutter.h> #import <Flutter/Flutter.h>
@implementation AppDelegate { @implementation AppDelegate
} - (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
- (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; return YES;
} }
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<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"> <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> <dependencies>
<deployment identifier="iOS"/> <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> </dependencies>
<scenes> <scenes>
<!--View Controller--> <!--View Controller-->
...@@ -14,9 +18,9 @@ ...@@ -14,9 +18,9 @@
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/> <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> <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"/> <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> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
#import "AppDelegate.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 { @autoreleasepool {
return UIApplicationMain(argc, argv, nil, return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class])); NSStringFromClass([AppDelegate class]));
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
...@@ -19,16 +18,12 @@ class _PlatformServicesState extends State<PlatformServices> { ...@@ -19,16 +18,12 @@ class _PlatformServicesState extends State<PlatformServices> {
Future<Null> _getBatteryLevel() async { Future<Null> _getBatteryLevel() async {
String batteryLevel; String batteryLevel;
if (Platform.isIOS) {
batteryLevel = "iOS is not supported yet.";
} else {
try { try {
final int result = await platform.invokeMethod('getBatteryLevel'); final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level at $result % .'; batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) { } on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'."; batteryLevel = "Failed to get battery level: '${e.message}'.";
} }
}
setState(() { setState(() {
_batteryLevel = batteryLevel; _batteryLevel = batteryLevel;
}); });
...@@ -45,10 +40,10 @@ class _PlatformServicesState extends State<PlatformServices> { ...@@ -45,10 +40,10 @@ class _PlatformServicesState extends State<PlatformServices> {
child: new Text('Get Battery Level'), child: new Text('Get Battery Level'),
onPressed: _getBatteryLevel, onPressed: _getBatteryLevel,
), ),
new Text(_batteryLevel) new Text(_batteryLevel),
], ],
) ),
) ),
); );
} }
} }
......
...@@ -11,8 +11,7 @@ import 'package:typed_data/typed_buffers.dart' show Uint8Buffer; ...@@ -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 /// A WriteBuffer instance can be used only once. Attempts to reuse will result
/// in [NoSuchMethodError]s being thrown. /// in [NoSuchMethodError]s being thrown.
/// ///
/// The byte order of serialized data is [Endianness.BIG_ENDIAN]. /// The byte order used is [Endianness.HOST_ENDIAN] throughout.
/// The byte order of deserialized data is [Endianness.HOST_ENDIAN].
class WriteBuffer { class WriteBuffer {
WriteBuffer() { WriteBuffer() {
_buffer = new Uint8Buffer(); _buffer = new Uint8Buffer();
...@@ -28,26 +27,28 @@ class WriteBuffer { ...@@ -28,26 +27,28 @@ class WriteBuffer {
_buffer.add(byte); _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) { void putInt32(int value) {
putUint8(value >> 24); _eightBytes.setInt32(0, value, Endianness.HOST_ENDIAN);
putUint8(value >> 16); _buffer.addAll(_eightBytesAsList, 0, 4);
putUint8(value >> 8);
putUint8(value);
} }
void putInt64(int value) { void putInt64(int value) {
putUint8(value >> 56); _eightBytes.setInt64(0, value, Endianness.HOST_ENDIAN);
putUint8(value >> 48); _buffer.addAll(_eightBytesAsList, 0, 8);
putUint8(value >> 40);
putUint8(value >> 32);
putUint8(value >> 24);
putUint8(value >> 16);
putUint8(value >> 8);
putUint8(value);
} }
void putFloat64(double value) { void putFloat64(double value) {
_eightBytes.setFloat64(0, value); _eightBytes.setFloat64(0, value, Endianness.HOST_ENDIAN);
_buffer.addAll(_eightBytesAsList); _buffer.addAll(_eightBytesAsList);
} }
...@@ -57,32 +58,17 @@ class WriteBuffer { ...@@ -57,32 +58,17 @@ class WriteBuffer {
void putInt32List(Int32List list) { void putInt32List(Int32List list) {
_alignTo(4); _alignTo(4);
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length)); _buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length));
} else {
for (final int value in list)
putInt32(value);
}
} }
void putInt64List(Int64List list) { void putInt64List(Int64List list) {
_alignTo(8); _alignTo(8);
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length)); _buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length));
} else {
for (final int value in list)
putInt64(value);
}
} }
void putFloat64List(Float64List list) { void putFloat64List(Float64List list) {
_alignTo(8); _alignTo(8);
if (Endianness.HOST_ENDIAN == Endianness.BIG_ENDIAN) {
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length)); _buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length));
} else {
for (final double value in list)
putFloat64(value);
}
} }
void _alignTo(int alignment) { void _alignTo(int alignment) {
...@@ -102,8 +88,7 @@ class WriteBuffer { ...@@ -102,8 +88,7 @@ class WriteBuffer {
/// Read-only buffer for reading sequentially from a [ByteData] instance. /// Read-only buffer for reading sequentially from a [ByteData] instance.
/// ///
/// The byte order of serialized data is [Endianness.BIG_ENDIAN]. /// The byte order used is [Endianness.HOST_ENDIAN] throughout.
/// The byte order of deserialized data is [Endianness.HOST_ENDIAN].
class ReadBuffer { class ReadBuffer {
final ByteData data; final ByteData data;
int position = 0; int position = 0;
...@@ -117,20 +102,32 @@ class ReadBuffer { ...@@ -117,20 +102,32 @@ class ReadBuffer {
return data.getUint8(position++); 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() { int getInt32() {
final int value = data.getInt32(position); final int value = data.getInt32(position, Endianness.HOST_ENDIAN);
position += 4; position += 4;
return value; return value;
} }
int getInt64() { int getInt64() {
final int value = data.getInt64(position); final int value = data.getInt64(position, Endianness.HOST_ENDIAN);
position += 8; position += 8;
return value; return value;
} }
double getFloat64() { double getFloat64() {
final double value = data.getFloat64(position); final double value = data.getFloat64(position, Endianness.HOST_ENDIAN);
position += 8; position += 8;
return value; return value;
} }
...@@ -143,45 +140,21 @@ class ReadBuffer { ...@@ -143,45 +140,21 @@ class ReadBuffer {
Int32List getInt32List(int length) { Int32List getInt32List(int length) {
_alignTo(4); _alignTo(4);
Int32List list; final Int32List list = data.buffer.asInt32List(data.offsetInBytes + position, length);
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);
}
position += 4 * length; position += 4 * length;
return list; return list;
} }
Int64List getInt64List(int length) { Int64List getInt64List(int length) {
_alignTo(8); _alignTo(8);
Int64List list; final Int64List list = data.buffer.asInt64List(data.offsetInBytes + position, length);
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);
}
position += 8 * length; position += 8 * length;
return list; return list;
} }
Float64List getFloat64List(int length) { Float64List getFloat64List(int length) {
_alignTo(8); _alignTo(8);
Float64List list; final Float64List list = data.buffer.asFloat64List(data.offsetInBytes + position, length);
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);
}
position += 8 * length; position += 8 * length;
return list; return list;
} }
......
...@@ -136,21 +136,20 @@ class StandardMessageCodec implements MessageCodec<dynamic> { ...@@ -136,21 +136,20 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
// * A single byte with one of the constant values below determines the // * A single byte with one of the constant values below determines the
// type of the value. // type of the value.
// * The serialization of the value itself follows the type byte. // * 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 // * Lengths and sizes of serialized parts are encoded using an expanding
// format optimized for the common case of small non-negative integers: // format optimized for the common case of small non-negative integers:
// * values 0..253 inclusive using one byte with that value; // * values 0..253 inclusive using one byte with that value;
// * values 254..2^16 inclusive using three bytes, the first of which is // * 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 // 254, the next two the usual unsigned representation of the value;
// value;
// * values 2^16+1..2^32 inclusive using five bytes, the first of which is // * 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 // 255, the next four the usual unsigned representation of the value.
// value.
// * null, true, and false have empty serialization; they are encoded directly // * null, true, and false have empty serialization; they are encoded directly
// in the type byte (using _kNull, _kTrue, _kFalse) // in the type byte (using _kNull, _kTrue, _kFalse)
// * Integers representable in 32 bits are encoded using 4 bytes big-endian, // * Integers representable in 32 bits are encoded using 4 bytes two's
// two's complement representation. // complement representation.
// * Larger integers representable in 64 bits are encoded using 8 bytes // * Larger integers representable in 64 bits are encoded using 8 bytes two's
// big-endian, two's complement representation. // complement representation.
// * Still larger integers are encoded using their hexadecimal string // * Still larger integers are encoded using their hexadecimal string
// representation. First the length of that is encoded in the expanding // representation. First the length of that is encoded in the expanding
// format, then follows the UTF-8 representation of the hex string. // format, then follows the UTF-8 representation of the hex string.
...@@ -164,8 +163,7 @@ class StandardMessageCodec implements MessageCodec<dynamic> { ...@@ -164,8 +163,7 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
// smallest number of zero bytes needed to align the position in the full // 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 // 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 // encoding of the list elements themselves, end-to-end with no additional
// type information, using big-endian two's complement or IEEE 754 as // type information, using two's complement or IEEE 754 as applicable.
// applicable.
// * Lists are encoded by first encoding their length in the expanding format, // * Lists are encoded by first encoding their length in the expanding format,
// then follows the recursive encoding of each element value, including the // then follows the recursive encoding of each element value, including the
// type byte (Lists are assumed to be heterogeneous). // type byte (Lists are assumed to be heterogeneous).
...@@ -215,14 +213,10 @@ class StandardMessageCodec implements MessageCodec<dynamic> { ...@@ -215,14 +213,10 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
buffer.putUint8(value); buffer.putUint8(value);
} else if (value <= 0xffff) { } else if (value <= 0xffff) {
buffer.putUint8(254); buffer.putUint8(254);
buffer.putUint8(value >> 8); buffer.putUint16(value);
buffer.putUint8(value);
} else { } else {
buffer.putUint8(255); buffer.putUint8(255);
buffer.putUint8(value >> 24); buffer.putUint32(value);
buffer.putUint8(value >> 16);
buffer.putUint8(value >> 8);
buffer.putUint8(value);
} }
} }
...@@ -288,17 +282,12 @@ class StandardMessageCodec implements MessageCodec<dynamic> { ...@@ -288,17 +282,12 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
static int _readSize(ReadBuffer buffer) { static int _readSize(ReadBuffer buffer) {
final int value = buffer.getUint8(); final int value = buffer.getUint8();
if (value < 254) { if (value < 254)
return value; return value;
} else if (value == 254) { else if (value == 254)
return (buffer.getUint8() << 8) return buffer.getUint16();
| buffer.getUint8(); else
} else { return buffer.getUint32();
return (buffer.getUint8() << 24)
| (buffer.getUint8() << 16)
| (buffer.getUint8() << 8)
| buffer.getUint8();
}
} }
static dynamic _readValue(ReadBuffer buffer) { 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