• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.dialer.about;
18 
19 import android.content.Context;
20 import android.content.res.Resources;
21 import com.android.dialer.common.Assert;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.UnsupportedEncodingException;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 
29 /** A helper for extracting licenses. */
30 public final class Licenses {
31   private static final String TAG = "Licenses";
32   private static final String LICENSE_FILENAME = "third_party_licenses";
33   private static final String LICENSE_METADATA_FILENAME = "third_party_license_metadata";
34 
35   /** Return the licenses bundled into this app. */
getLicenses(Context context)36   public static ArrayList<License> getLicenses(Context context) {
37     return getLicenseListFromMetadata(
38         getTextFromResource(context.getApplicationContext(), LICENSE_METADATA_FILENAME, 0, -1));
39   }
40 
41   /**
42    * Returns a list of {@link License}s parsed from a license metadata file.
43    *
44    * @param metadata a {@code String} containing the contents of a license metadata file.
45    */
getLicenseListFromMetadata(String metadata)46   private static ArrayList<License> getLicenseListFromMetadata(String metadata) {
47     String[] entries = metadata.split("\n");
48     ArrayList<License> licenses = new ArrayList<License>(entries.length);
49     for (String entry : entries) {
50       int delimiter = entry.indexOf(' ');
51       String[] licenseLocation = entry.substring(0, delimiter).split(":");
52       Assert.checkState(
53           delimiter > 0 && licenseLocation.length == 2,
54           "Invalid license meta-data line:\n" + entry);
55       long licenseOffset = Long.parseLong(licenseLocation[0]);
56       int licenseLength = Integer.parseInt(licenseLocation[1]);
57       licenses.add(License.create(entry.substring(delimiter + 1), licenseOffset, licenseLength));
58     }
59     Collections.sort(licenses);
60     return licenses;
61   }
62 
63   /** Return the text of a bundled license file. */
getLicenseText(Context context, License license)64   public static String getLicenseText(Context context, License license) {
65     long offset = license.getLicenseOffset();
66     int length = license.getLicenseLength();
67     return getTextFromResource(context, LICENSE_FILENAME, offset, length);
68   }
69 
getTextFromResource( Context context, String filename, long offset, int length)70   private static String getTextFromResource(
71       Context context, String filename, long offset, int length) {
72     Resources resources = context.getApplicationContext().getResources();
73     // When aapt is called with --rename-manifest-package, the package name is changed for the
74     // application, but not for the resources. This is to find the package name of a known
75     // resource to know what package to lookup the license files in.
76     String packageName = resources.getResourcePackageName(R.id.license);
77     InputStream stream =
78         resources.openRawResource(resources.getIdentifier(filename, "raw", packageName));
79     return getTextFromInputStream(stream, offset, length);
80   }
81 
getTextFromInputStream(InputStream stream, long offset, int length)82   private static String getTextFromInputStream(InputStream stream, long offset, int length) {
83     byte[] buffer = new byte[1024];
84     ByteArrayOutputStream textArray = new ByteArrayOutputStream();
85 
86     try {
87       stream.skip(offset);
88       int bytesRemaining = length > 0 ? length : Integer.MAX_VALUE;
89       int bytes = 0;
90 
91       while (bytesRemaining > 0
92           && (bytes = stream.read(buffer, 0, Math.min(bytesRemaining, buffer.length))) != -1) {
93         textArray.write(buffer, 0, bytes);
94         bytesRemaining -= bytes;
95       }
96       stream.close();
97     } catch (IOException e) {
98       throw new RuntimeException("Failed to read license or metadata text.", e);
99     }
100     try {
101       return textArray.toString("UTF-8");
102     } catch (UnsupportedEncodingException e) {
103       throw new RuntimeException("Unsupported encoding UTF8. This should always be supported.", e);
104     }
105   }
106 }
107