Licenses.java revision 633eb826b8c97731dfc5ef12c7bf78a63734275d
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.tv.license; 18 19import android.content.Context; 20import android.support.annotation.RawRes; 21 22import com.android.tv.R; 23import com.android.tv.common.SoftPreconditions; 24 25import java.io.ByteArrayOutputStream; 26import java.io.IOException; 27import java.io.InputStream; 28import java.io.UnsupportedEncodingException; 29import java.util.ArrayList; 30import java.util.Collections; 31 32/** 33 * A helper for extracting licenses embedded using 34 * third_party_licenses.build:third_party_licenses(). 35 */ 36public final class Licenses { 37 38 public static final String TAG = "Licenses"; 39 public static boolean hasLicenses(Context context) { 40 return !getTextFromResource( 41 context.getApplicationContext(), R.raw.third_party_license_metadata, 0, -1) 42 .isEmpty(); 43 } 44 45 /** Return the licenses bundled into this app. */ 46 public static ArrayList<License> getLicenses(Context context) { 47 return getLicenseListFromMetadata( 48 getTextFromResource( 49 context.getApplicationContext(), R.raw.third_party_license_metadata, 0, -1), 50 ""); 51 } 52 53 /** 54 * Returns a list of {@link License}s parsed from a license metadata file. 55 * 56 * @param metadata a {@code String} containing the contents of a license metadata file. 57 * @param filePath a path to a package archive with licenses or empty string for the app package 58 */ 59 private static ArrayList<License> getLicenseListFromMetadata(String metadata, String filePath) { 60 String[] entries = metadata.split("\n"); 61 ArrayList<License> licenses = new ArrayList<License>(entries.length); 62 for (String entry : entries) { 63 int delimiter = entry.indexOf(' '); 64 String[] licenseLocation = entry.substring(0, delimiter).split(":"); 65 SoftPreconditions.checkState( 66 licenseLocation.length == 2 && delimiter > 0, 67 TAG, 68 "Invalid license meta-data line:\n" + entry); 69 long licenseOffset = Long.parseLong(licenseLocation[0]); 70 int licenseLength = Integer.parseInt(licenseLocation[1]); 71 licenses.add( 72 License.create( 73 entry.substring(delimiter + 1), 74 licenseOffset, 75 licenseLength, 76 filePath)); 77 } 78 Collections.sort(licenses); 79 return licenses; 80 } 81 82 /** Return the text of a bundled license file. */ 83 public static String getLicenseText(Context context, License license) { 84 long offset = license.getLicenseOffset(); 85 int length = license.getLicenseLength(); 86 return getTextFromResource(context, R.raw.third_party_licenses, offset, length); 87 } 88 89 private static String getTextFromResource( 90 Context context, @RawRes int resourcesIdentifier, long offset, int length) { 91 InputStream stream = 92 context.getApplicationContext().getResources().openRawResource(resourcesIdentifier); 93 return getTextFromInputStream(stream, offset, length); 94 } 95 96 private static String getTextFromInputStream(InputStream stream, long offset, int length) { 97 byte[] buffer = new byte[1024]; 98 ByteArrayOutputStream textArray = new ByteArrayOutputStream(); 99 100 try { 101 stream.skip(offset); 102 int bytesRemaining = length > 0 ? length : Integer.MAX_VALUE; 103 int bytes = 0; 104 105 while (bytesRemaining > 0 106 && (bytes = stream.read(buffer, 0, Math.min(bytesRemaining, buffer.length))) 107 != -1) { 108 textArray.write(buffer, 0, bytes); 109 bytesRemaining -= bytes; 110 } 111 stream.close(); 112 } catch (IOException e) { 113 throw new RuntimeException("Failed to read license or metadata text.", e); 114 } 115 try { 116 return textArray.toString("UTF-8"); 117 } catch (UnsupportedEncodingException e) { 118 throw new RuntimeException( 119 "Unsupported encoding UTF8. This should always be supported.", e); 120 } 121 } 122} 123