blob: 0bea316192f31cebd005ce1f5422c5535ed43b65 [file] [log] [blame]
/*
* 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;
}
}