• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.google.android.downloader;
16 
17 import static com.google.common.base.Preconditions.checkState;
18 
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.nio.channels.SelectableChannel;
22 import java.nio.channels.WritableByteChannel;
23 
24 /** Package-local utilities for facilitating common I/O operations across engine implementations. */
25 final class IOUtil {
26 
IOUtil()27   private IOUtil() {}
28 
29   /**
30    * Validates the given channel as a valid byte sink for the UrlEngine library. Specifically, it
31    * checks that the given channel is open, and if it is a {@link SelectableChannel}, then it must
32    * be in blocking mode.
33    *
34    * <p>This is to guard against having a sink that refuses write operations in a non-blocking
35    * manner by returning from {@link WritableByteChannel#write} immediately with a return value of
36    * 0, indicating no bytes were written. That would be problematic for the UrlEngine library
37    * because then threads will spin constantly trying to stream bytes from the source to the sink,
38    * saturating the CPU in the process.
39    *
40    * <p>TODO: Figure out a more robust way to handle this. Maybe writing implement proper support
41    * for selectable channels?
42    */
validateChannel(WritableByteChannel channel)43   static void validateChannel(WritableByteChannel channel) {
44     if (channel instanceof SelectableChannel) {
45       SelectableChannel selectableChannel = (SelectableChannel) channel;
46       checkState(
47           selectableChannel.isBlocking(),
48           "Target channels used by UrlEngine must be in blocking mode to ensure "
49               + "writes happen correctly; call SelectableChannel#configureBlocking(true).");
50     }
51 
52     checkState(channel.isOpen());
53   }
54 
blockingWrite(ByteBuffer source, WritableByteChannel target)55   static long blockingWrite(ByteBuffer source, WritableByteChannel target) throws IOException {
56     long written = 0;
57     while (source.hasRemaining()) {
58       written += target.write(source);
59     }
60     return written;
61   }
62 }
63