public void Create_NegativeCapacity_ThrowsArgumentOutOfRangeException() { AssertExtensions.Throws <ArgumentOutOfRangeException>("capacity", () => WindowsRuntimeBuffer.Create(-1)); AssertExtensions.Throws <ArgumentOutOfRangeException>("capacity", () => WindowsRuntimeBuffer.Create(new byte[0], 0, 0, -1)); }
} // ReadAsync_MemoryStream internal static IAsyncOperationWithProgress <IBuffer, uint> ReadAsync_AbstractStream(Stream stream, IBuffer buffer, uint count, InputStreamOptions options) { Debug.Assert(stream != null); Debug.Assert(stream.CanRead); Debug.Assert(buffer != null); Debug.Assert(buffer is IBufferByteAccess); Debug.Assert(0 <= count); Debug.Assert(count <= int.MaxValue); Debug.Assert(count <= buffer.Capacity); Debug.Assert(options == InputStreamOptions.None || options == InputStreamOptions.Partial || options == InputStreamOptions.ReadAhead); int bytesRequested = (int)count; // Check if the buffer is our implementation. // IF YES: In that case, we can read directly into its data array. // IF NO: The buffer is of unknown implementation. It's not backed by a managed array, but the wrapped stream can only // read into a managed array. If we used the user-supplied buffer we would need to copy data into it after every read. // The spec allows to return a buffer instance that is not the same as passed by the user. So, we will create an own // buffer instance, read data *directly* into the array backing it and then return it to the user. // Note: the allocation costs we are paying for the new buffer are unavoidable anyway, as we we would need to create // an array to read into either way. IBuffer dataBuffer = buffer as WindowsRuntimeBuffer; if (dataBuffer == null) { dataBuffer = WindowsRuntimeBuffer.Create((int)Math.Min((uint)int.MaxValue, buffer.Capacity)); } // This operation delegate will we run inside of the returned IAsyncOperationWithProgress: Func <CancellationToken, IProgress <uint>, Task <IBuffer> > readOperation = async(cancelToken, progressListener) => { // No bytes read yet: dataBuffer.Length = 0; // Get the buffer backing array: byte[] data; int offset; bool managedBufferAssert = dataBuffer.TryGetUnderlyingData(out data, out offset); Debug.Assert(managedBufferAssert); // Init tracking values: bool done = cancelToken.IsCancellationRequested; int bytesCompleted = 0; // Loop until EOS, cancelled or read enough data according to options: while (!done) { int bytesRead = 0; try { // Read asynchronously: bytesRead = await stream.ReadAsync(data, offset + bytesCompleted, bytesRequested - bytesCompleted, cancelToken) .ConfigureAwait(continueOnCapturedContext: false); // We will continue here on a different thread when read async completed: bytesCompleted += bytesRead; // We will handle a cancelation exception and re-throw all others: } catch (OperationCanceledException) { // We assume that cancelToken.IsCancellationRequested is has been set and simply proceed. // (we check cancelToken.IsCancellationRequested later) Debug.Assert(cancelToken.IsCancellationRequested); // This is because if the cancellation came after we read some bytes we want to return the results we got instead // of an empty cancelled task, so if we have not yet read anything at all, then we can throw cancellation: if (bytesCompleted == 0 && bytesRead == 0) { throw; } } // Update target buffer: dataBuffer.Length = (uint)bytesCompleted; Debug.Assert(bytesCompleted <= bytesRequested); // Check if we are done: done = options == InputStreamOptions.Partial || // If no complete read was requested, any amount of data is OK bytesRead == 0 || // this implies EndOfStream bytesCompleted == bytesRequested || // read all requested bytes cancelToken.IsCancellationRequested; // operation was cancelled // Call user Progress handler: if (progressListener != null) { progressListener.Report(dataBuffer.Length); } } // while (!done) // If we got here, then no error was detected. Return the results buffer: return(dataBuffer); }; // readOperation return(AsyncInfo.Run <IBuffer, UInt32>(readOperation)); } // ReadAsync_AbstractStream
private static void DoTestRead(Func <IInputStream> createStreamFunc, InputStreamOptions inputStreamOptions, bool mustInvokeProgressHandler, bool completesSynchronously) { IInputStream stream = createStreamFunc(); IBuffer buffer = WindowsRuntimeBuffer.Create(TestStreamProvider.ModelStreamLength); IAsyncOperationWithProgress <IBuffer, uint> readOp = stream.ReadAsync(buffer, (uint)TestStreamProvider.ModelStreamLength, inputStreamOptions); if (completesSynchronously) { // New readOp for a stream where we know that reading is sycnhronous must have Status = Completed Assert.Equal(AsyncStatus.Completed, readOp.Status); } else { // Note the race. By the tie we get here, the status of the op may be started or already completed. AsyncStatus readOpStatus = readOp.Status; Assert.True(readOpStatus == AsyncStatus.Completed || readOpStatus == AsyncStatus.Started, "New readOp must have Status = Started or Completed (race)"); } bool progressCallbackInvoked = false; bool completedCallbackInvoked = false; uint readOpId = readOp.Id; EventWaitHandle waitHandle = new ManualResetEvent(false); readOp.Progress = (asyncReadOp, bytesCompleted) => { progressCallbackInvoked = true; // asyncReadOp.Id in a progress callback must match the ID of the asyncReadOp to which the callback was assigned Assert.Equal(readOpId, asyncReadOp.Id); // asyncReadOp.Status must be 'Started' for an asyncReadOp in progress Assert.Equal(AsyncStatus.Started, asyncReadOp.Status); // bytesCompleted must be in range [0, maxBytesToRead] asyncReadOp in progress Assert.InRange(bytesCompleted, 0u, (uint)TestStreamProvider.ModelStreamLength); }; readOp.Completed = (asyncReadOp, passedStatus) => { try { completedCallbackInvoked = true; // asyncReadOp.Id in a completion callback must match the ID of the asyncReadOp to which the callback was assigned Assert.Equal(readOpId, asyncReadOp.Id); // asyncReadOp.Status must match passedStatus for a completed asyncReadOp Assert.Equal(passedStatus, asyncReadOp.Status); // asyncReadOp.Status must be 'Completed' for a completed asyncReadOp Assert.Equal(AsyncStatus.Completed, asyncReadOp.Status); IBuffer resultBuffer = asyncReadOp.GetResults(); // asyncReadOp.GetResults() must not return null for a completed asyncReadOp Assert.NotNull(resultBuffer); AssertExtensions.GreaterThan(resultBuffer.Capacity, 0u, "resultBuffer.Capacity should be more than zero in completed callback"); AssertExtensions.GreaterThan(resultBuffer.Length, 0u, "resultBuffer.Length should be more than zero in completed callback"); AssertExtensions.LessThanOrEqualTo(resultBuffer.Length, resultBuffer.Capacity, "resultBuffer.Length should be <= Capacity in completed callback"); if (inputStreamOptions == InputStreamOptions.None) { // resultBuffer.Length must be equal to requested number of bytes when an asyncReadOp with // InputStreamOptions.None completes successfully Assert.Equal(resultBuffer.Length, (uint)TestStreamProvider.ModelStreamLength); } if (inputStreamOptions == InputStreamOptions.Partial) { AssertExtensions.LessThanOrEqualTo(resultBuffer.Length, (uint)TestStreamProvider.ModelStreamLength, "resultBuffer.Length must be <= requested number of bytes with InputStreamOptions.Partial in completed callback"); } buffer = resultBuffer; } finally { waitHandle.Set(); } }; // Now, let's block until the read op is complete. // We speculate that it will complete within 3500 msec, although under high load it may not be. // If the test fails we should use a better way to determine if callback is really not invoked, or if it's just too slow. waitHandle.WaitOne(500); waitHandle.WaitOne(1000); waitHandle.WaitOne(2000); if (mustInvokeProgressHandler) { Assert.True(progressCallbackInvoked, "Progress callback specified to ReadAsync callback must be invoked when reading from this kind of stream"); } Assert.True(completedCallbackInvoked, "Completion callback specified to ReadAsync callback must be invoked"); // readOp.Status must be 'Completed' for a completed async readOp Assert.Equal(AsyncStatus.Completed, readOp.Status); AssertExtensions.GreaterThan(buffer.Capacity, 0u, "buffer.Capacity should be greater than zero bytes"); AssertExtensions.GreaterThan(buffer.Length, 0u, "buffer.Length should be greater than zero bytes"); AssertExtensions.LessThanOrEqualTo(buffer.Length, buffer.Capacity, "buffer.Length <= buffer.Capacity is required for a completed async readOp"); if (inputStreamOptions == InputStreamOptions.None) { // buffer.Length must be equal to requested number of bytes when an async readOp with // InputStreamOptions.None completes successfully Assert.Equal((uint)TestStreamProvider.ModelStreamLength, buffer.Length); } if (inputStreamOptions == InputStreamOptions.Partial) { AssertExtensions.LessThanOrEqualTo(buffer.Length, (uint)TestStreamProvider.ModelStreamLength, "resultBuffer.Length must be <= requested number of bytes with InputStreamOptions.Partial"); } byte[] results = new byte[buffer.Length]; buffer.CopyTo(0, results, 0, (int)buffer.Length); Assert.True(TestStreamProvider.CheckContent(results, 0, (int)buffer.Length), "Result data returned from AsyncRead must be the same as expected from the test data source"); }
private void SetCommands() { AddAttachmentCommand = new RelayCommand(async() => { var picker = new FileOpenPicker(); picker.ViewMode = PickerViewMode.List; picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary; picker.FileTypeFilter.Add("*"); var files = await picker.PickMultipleFilesAsync(); foreach (var file in files) { byte[] bytes = null; using (var stream = await file.OpenReadAsync()) { IBuffer buffer = WindowsRuntimeBuffer.Create((int)stream.Size); await stream.ReadAsync(buffer, (uint)stream.Size, InputStreamOptions.None); bytes = buffer.ToArray(); } var attach = new FeedbackAttachment(file.Name, bytes, file.ContentType); this.Attachments.Add(new FeedbackAttachmentVM(attach) { FeedbackMessageVM = this }); } }); OpenAttachmentCommand = new RelayCommand(async(o) => { await((FeedbackAttachmentVM)o).OpenAttachmentAsync(); }); SendMessageCommand = new RelayCommand(async(o) => { bool success = true; if (await ValidateInputAsync()) { if (NetworkInterface.GetIsNetworkAvailable()) { this.IsBusy = true; try { IFeedbackMessage sentMessage = await this.SendFeedbackAsync(); this.FeedbackThreadVM.HandleSentMessage(sentMessage); } catch (Exception e) { HockeyClient.Current.AsInternal().HandleInternalUnhandledException(e); success = false; } finally { this.IsBusy = false; } if (!success) { await new MessageDialog(LocalizedStrings.LocalizedResources.FeedbackSendError).ShowAsync(); FeedbackFlyoutVM.ShowFlyout(); } } else { await new MessageDialog(LocalizedStrings.LocalizedResources.FeedbackNoInternet).ShowAsync(); FeedbackFlyoutVM.ShowFlyout(); } } else { FeedbackFlyoutVM.ShowFlyout(); } }); CancelMessageCommand = new RelayCommand((o) => { this.Message = null; this.Attachments.Clear(); }); if (!String.IsNullOrWhiteSpace(this.Email)) { Task t = this.ReLoadGravatar(); } else { this.Gravatar = GravatarHelper.DefaultGravatar; } }
/// <summary> /// Asynchronous initialization /// </summary> /// <returns>Initialization Task</returns> public override async Task Init() { var serviceData = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, }; ServiceData = WindowsRuntimeBuffer.Create(serviceData, 0, serviceData.Length, serviceData.Length); await CreateServiceProvider(MSFTServiceUuid); GattLocalCharacteristicResult result = null; // Prepare the Read Characteristic GattLocalCharacteristicParameters readParam = PlainReadParameter; readParam.UserDescription = "Microsoft Read characteristic"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor readParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.Signed32BitInteger), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseReadChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTReadChar, readParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseReadChar); if (baseReadChar != null) { ReadCharacteristic = new Characteristics.MicrosoftReadCharacteristic(baseReadChar, this); } result = null; // Prepare the Write Characteristic GattLocalCharacteristicParameters writeParam = PlainWriteOrWriteWithoutRespondsParameter; writeParam.UserDescription = "Microsoft Write characteristic"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor writeParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.UTF8String), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseWriteChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTWriteChar, writeParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseWriteChar); if (baseWriteChar != null) { WriteCharacteristic = new Characteristics.MicrosoftWriteCharacteristic(baseWriteChar, this); } result = null; // Prepare the Notify Characteristic GattLocalCharacteristicParameters notifyParam = PlainReadNotifyParameters; notifyParam.UserDescription = "Microsoft Notify characteristic"; // Add presentation format - string, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor notifyParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.UTF8String), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseNotifyChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTNotifyChar, notifyParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseNotifyChar); if (baseNotifyChar != null) { NotifyCharacteristic = new Characteristics.MicrosoftNotifyCharacteristic(baseNotifyChar, this); } result = null; // Prepare the Indicate Characteristic GattLocalCharacteristicParameters indicateParam = new GattLocalCharacteristicParameters { CharacteristicProperties = GattCharacteristicProperties.Read | GattCharacteristicProperties.Indicate, WriteProtectionLevel = GattProtectionLevel.Plain, ReadProtectionLevel = GattProtectionLevel.Plain }; indicateParam.UserDescription = "Microsoft Indicate characteristic"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor indicateParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.UTF8String), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseIndicateChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTIndicateChar, indicateParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseIndicateChar); if (baseIndicateChar != null) { IndicateCharacteristic = new Characteristics.MicrosoftNotifyCharacteristic(baseIndicateChar, this); } result = null; // Prepare the Read Long Characteristic GattLocalCharacteristicParameters longParam = new GattLocalCharacteristicParameters { CharacteristicProperties = GattCharacteristicProperties.Read, WriteProtectionLevel = GattProtectionLevel.Plain, ReadProtectionLevel = GattProtectionLevel.Plain }; longParam.UserDescription = "Microsoft Read Long characteristic"; // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor longParam.PresentationFormats.Add( GattPresentationFormat.FromParts( Convert.ToByte(PresentationFormats.FormatTypes.OpaqueStructure), PresentationFormats.Exponent, Convert.ToUInt16(PresentationFormats.Units.Unitless), Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber), PresentationFormats.Description)); GattLocalCharacteristic baseLongReadChar = null; result = await ServiceProvider.Service.CreateCharacteristicAsync(MSFTLongChar, longParam); GattServicesHelper.GetCharacteristicsFromResult(result, ref baseLongReadChar); if (baseLongReadChar != null) { ReadLongCharacteristic = new Characteristics.MicrosoftReadLongCharacteristic(baseLongReadChar, this); } result = null; }
public async Task ToggleStream(bool start) { if (start == isStreaming) { return; } try { if (start) { if (channels == null) { channels = new List <GattCharacteristic>(); } // Get GATT service on start, therefore it will be already available when stopping. deviceService = (await Device.GetGattServicesForUuidAsync(Constants.MUSE_DATA_SERVICE_UUID)).Services.First(); } var characteristics = (await deviceService.GetCharacteristicsAsync()).Characteristics; foreach (var c in channelUUIDs) { var characteristic = characteristics.SingleOrDefault(x => x.Uuid == c); if (characteristic == null) { Log.Error($"Unexpected null GATT characteristic (UUID={c}) during toggle stream (start={start})."); return; } channels.Add(characteristic); } GattClientCharacteristicConfigurationDescriptorValue notify; byte[] toggleData; if (start) { notify = GattClientCharacteristicConfigurationDescriptorValue.Notify; toggleData = Constants.MUSE_TOGGLE_STREAM_START; } else { notify = GattClientCharacteristicConfigurationDescriptorValue.None; toggleData = Constants.MUSE_TOGGLE_STREAM_STOP; } var buffer = WindowsRuntimeBuffer.Create(toggleData, 0, toggleData.Length, toggleData.Length); for (int i = 0; i < channels.Count; i++) { if (start) { channels[i].ValueChanged += Channel_ValueChanged; sampleBuffer = new Dictionary <ushort, MuseSample>(); } else { channels[i].ValueChanged -= Channel_ValueChanged; } await channels[i].WriteClientCharacteristicConfigurationDescriptorAsync(notify); } // Tell Muse to start or stop notifications. await characteristics.Single(x => x.Uuid == Constants.MUSE_TOGGLE_STREAM_UUID).WriteValueWithResultAsync(buffer); } catch (Exception ex) { Log.Error($"Exception during toggle stream (start={start}).", ex); if (isStreaming) { FinishCloseOffStream(); } return; } if (start) { FinishOpenStream(); } else { FinishCloseOffStream(); // Don't have to keep service reference around anymore. The handlers for the channels will also stop. } }