1 /* 2 * Copyright (C) 2017 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.google.android.mobly.snippet.bundled; 18 19 import android.app.DownloadManager; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.net.Uri; 25 import android.os.Environment; 26 import androidx.test.platform.app.InstrumentationRegistry; 27 import com.google.android.mobly.snippet.Snippet; 28 import com.google.android.mobly.snippet.bundled.utils.Utils; 29 import com.google.android.mobly.snippet.rpc.Rpc; 30 import com.google.android.mobly.snippet.util.Log; 31 import java.io.IOException; 32 import java.net.InetAddress; 33 import java.net.Socket; 34 import java.net.UnknownHostException; 35 import java.util.List; 36 import java.util.Locale; 37 38 /** Snippet class for networking RPCs. */ 39 public class NetworkingSnippet implements Snippet { 40 41 private final Context mContext; 42 private final DownloadManager mDownloadManager; 43 private volatile boolean mIsDownloadComplete = false; 44 private volatile long mReqid = 0; 45 NetworkingSnippet()46 public NetworkingSnippet() { 47 mContext = InstrumentationRegistry.getInstrumentation().getContext(); 48 mDownloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE); 49 } 50 51 private static class NetworkingSnippetException extends Exception { 52 53 private static final long serialVersionUID = 8080L; 54 NetworkingSnippetException(String msg)55 public NetworkingSnippetException(String msg) { 56 super(msg); 57 } 58 } 59 60 @Rpc(description = "Check if a host and port are connectable using a TCP connection attempt.") networkIsTcpConnectable(String host, int port)61 public boolean networkIsTcpConnectable(String host, int port) { 62 InetAddress addr; 63 try { 64 addr = InetAddress.getByName(host); 65 } catch (UnknownHostException uherr) { 66 Log.d("Host name lookup failure: " + uherr.getMessage()); 67 return false; 68 } 69 70 try { 71 Socket sock = new Socket(addr, port); 72 sock.close(); 73 } catch (IOException ioerr) { 74 Log.d("Did not make connection to host: " + ioerr.getMessage()); 75 return false; 76 } 77 return true; 78 } 79 80 @Rpc( 81 description = 82 "Download a file using HTTP. Return content Uri (file remains on device). " 83 + "The Uri should be treated as an opaque handle for further operations.") networkHttpDownload(String url)84 public String networkHttpDownload(String url) 85 throws IllegalArgumentException, NetworkingSnippetException { 86 87 Uri uri = Uri.parse(url); 88 List<String> pathsegments = uri.getPathSegments(); 89 if (pathsegments.size() < 1) { 90 throw new IllegalArgumentException( 91 String.format(Locale.US, "The Uri %s does not have a path.", uri.toString())); 92 } 93 DownloadManager.Request request = new DownloadManager.Request(uri); 94 request.setDestinationInExternalPublicDir( 95 Environment.DIRECTORY_DOWNLOADS, pathsegments.get(pathsegments.size() - 1)); 96 mIsDownloadComplete = false; 97 mReqid = 0; 98 IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); 99 BroadcastReceiver receiver = new DownloadReceiver(); 100 mContext.registerReceiver(receiver, filter); 101 try { 102 mReqid = mDownloadManager.enqueue(request); 103 Log.d( 104 String.format( 105 Locale.US, 106 "networkHttpDownload download of %s with id %d", 107 url, 108 mReqid)); 109 if (!Utils.waitUntil(() -> mIsDownloadComplete, 30)) { 110 Log.d( 111 String.format( 112 Locale.US, "networkHttpDownload timed out waiting for completion")); 113 throw new NetworkingSnippetException("networkHttpDownload timed out."); 114 } 115 } finally { 116 mContext.unregisterReceiver(receiver); 117 } 118 Uri resp = mDownloadManager.getUriForDownloadedFile(mReqid); 119 if (resp != null) { 120 Log.d(String.format(Locale.US, "networkHttpDownload completed to %s", resp.toString())); 121 mReqid = 0; 122 return resp.toString(); 123 } else { 124 Log.d( 125 String.format( 126 Locale.US, 127 "networkHttpDownload Failed to download %s", 128 uri.toString())); 129 throw new NetworkingSnippetException("networkHttpDownload didn't get downloaded file."); 130 } 131 } 132 133 private class DownloadReceiver extends BroadcastReceiver { 134 135 @Override onReceive(Context context, Intent intent)136 public void onReceive(Context context, Intent intent) { 137 String action = intent.getAction(); 138 long gotid = (long) intent.getExtras().get("extra_download_id"); 139 if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action) && gotid == mReqid) { 140 mIsDownloadComplete = true; 141 } 142 } 143 } 144 145 @Override shutdown()146 public void shutdown() { 147 if (mReqid != 0) { 148 mDownloadManager.remove(mReqid); 149 } 150 } 151 } 152