| /* |
| * Copyright 2016, The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.managedprovisioning.common; |
| |
| import android.accounts.Account; |
| import android.content.ComponentName; |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.net.Uri; |
| import android.os.PersistableBundle; |
| import android.util.Base64; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.IllformedLocaleException; |
| import java.util.Locale; |
| import java.util.function.Function; |
| |
| /** |
| * Class with Utils methods to store values in xml files, and to convert various |
| * types to and from string. |
| */ |
| public class StoreUtils { |
| public static final String ATTR_VALUE = "value"; |
| |
| /** |
| * Directory name under parent directory {@link Context#getFilesDir()} |
| * It's directory to cache all files / uri from external provisioning intent. |
| * Files must be prefixed by their own prefixes to avoid collisions. |
| */ |
| public static final String DIR_PROVISIONING_PARAMS_FILE_CACHE = |
| "provisioning_params_file_cache"; |
| |
| private static final String ATTR_ACCOUNT_NAME = "account-name"; |
| private static final String ATTR_ACCOUNT_TYPE = "account-type"; |
| |
| /** |
| * Reads an account from a {@link PersistableBundle}. |
| */ |
| public static Account persistableBundleToAccount(PersistableBundle bundle) { |
| return new Account( |
| bundle.getString(ATTR_ACCOUNT_NAME), |
| bundle.getString(ATTR_ACCOUNT_TYPE)); |
| } |
| |
| /** |
| * Writes an account to a {@link PersistableBundle}. |
| */ |
| public static PersistableBundle accountToPersistableBundle(Account account) { |
| final PersistableBundle bundle = new PersistableBundle(); |
| bundle.putString(ATTR_ACCOUNT_NAME, account.name); |
| bundle.putString(ATTR_ACCOUNT_TYPE, account.type); |
| return bundle; |
| } |
| |
| /** |
| * Serialize ComponentName. |
| */ |
| public static String componentNameToString(ComponentName componentName) { |
| return componentName == null ? null |
| : componentName.getPackageName() + "/" + componentName.getClassName(); |
| } |
| |
| /** |
| * Deserialize ComponentName. |
| * Don't use {@link ComponentName#unflattenFromString(String)}, because it doesn't keep |
| * original class name |
| */ |
| public static ComponentName stringToComponentName(String str) { |
| int sep = str.indexOf('/'); |
| if (sep < 0 || (sep+1) >= str.length()) { |
| return null; |
| } |
| String pkg = str.substring(0, sep); |
| String cls = str.substring(sep+1); |
| return new ComponentName(pkg, cls); |
| } |
| |
| /** |
| * Converts a String to a Locale. |
| */ |
| public static Locale stringToLocale(String string) throws IllformedLocaleException { |
| if (string != null) { |
| return new Locale.Builder().setLanguageTag(string.replace("_", "-")).build(); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Converts a Locale to a String. |
| */ |
| public static String localeToString(Locale locale) { |
| if (locale != null) { |
| return locale.toLanguageTag(); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Transforms a string into a byte array. |
| * |
| * @param s the string to be transformed |
| */ |
| public static byte[] stringToByteArray(String s) |
| throws NumberFormatException { |
| try { |
| return Base64.decode(s, Base64.URL_SAFE); |
| } catch (IllegalArgumentException e) { |
| throw new NumberFormatException("Incorrect format. Should be Url-safe Base64 encoded."); |
| } |
| } |
| |
| /** |
| * Transforms a byte array into a string. |
| * |
| * @param bytes the byte array to be transformed |
| */ |
| public static String byteArrayToString(byte[] bytes) { |
| return Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP); |
| } |
| |
| public static void putIntegerIfNotNull(PersistableBundle bundle, String attrName, |
| Integer integer) { |
| if (integer != null) { |
| bundle.putInt(attrName, integer); |
| } |
| } |
| |
| public static void putPersistableBundlableIfNotNull(PersistableBundle bundle, String attrName, |
| PersistableBundlable bundlable) { |
| if (bundlable != null) { |
| bundle.putPersistableBundle(attrName, bundlable.toPersistableBundle()); |
| } |
| } |
| |
| public static <E> E getObjectAttrFromPersistableBundle(PersistableBundle bundle, |
| String attrName, Function<PersistableBundle, E> converter) { |
| final PersistableBundle attrBundle = bundle.getPersistableBundle(attrName); |
| return attrBundle == null ? null : converter.apply(attrBundle); |
| } |
| |
| public static <E> E getStringAttrFromPersistableBundle(PersistableBundle bundle, |
| String attrName, Function<String, E> converter) { |
| final String str = bundle.getString(attrName); |
| return str == null ? null : converter.apply(str); |
| } |
| |
| public static Integer getIntegerAttrFromPersistableBundle(PersistableBundle bundle, |
| String attrName) { |
| return bundle.containsKey(attrName) ? bundle.getInt(attrName) : null; |
| } |
| |
| /** |
| * @return true if successfully copy the uri into the file. Otherwise, the outputFile will not |
| * be created. |
| */ |
| public static boolean copyUriIntoFile(ContentResolver cr, Uri uri, File outputFile) { |
| try (final InputStream in = cr.openInputStream(uri)) { // Throws SecurityException |
| try (final FileOutputStream out = new FileOutputStream(outputFile)) { |
| copyStream(in, out); |
| } |
| ProvisionLogger.logi("Successfully copy from uri " + uri + " to " + outputFile); |
| return true; |
| } catch (IOException | SecurityException e) { |
| ProvisionLogger.logi("Could not write file from " + uri + " to " |
| + outputFile, e); |
| // If the file was only partly written, delete it. |
| outputFile.delete(); |
| return false; |
| } |
| } |
| |
| public static String readString(File file) throws IOException { |
| try (final InputStream in = new FileInputStream(file)) { |
| try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) { |
| copyStream(in, out); |
| return out.toString(); |
| } |
| } |
| } |
| |
| public static void copyStream(final InputStream in, |
| final OutputStream out) throws IOException { |
| final byte buffer[] = new byte[1024]; |
| int bytesReadCount; |
| while ((bytesReadCount = in.read(buffer)) != -1) { |
| out.write(buffer, 0, bytesReadCount); |
| } |
| } |
| |
| public interface TextFileReader { |
| String read(File file) throws IOException; |
| } |
| } |