| /* |
| * Copyright (C) 2015 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.example.android.nfcprovisioning; |
| |
| import android.app.Activity; |
| import android.app.admin.DevicePolicyManager; |
| import android.content.Context; |
| import android.net.wifi.WifiInfo; |
| import android.net.wifi.WifiManager; |
| import android.os.Environment; |
| import android.support.v4.content.AsyncTaskLoader; |
| |
| import com.example.android.common.logger.Log; |
| |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.io.StringWriter; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| import java.util.TimeZone; |
| |
| /** |
| * Loads default values for NFC provisioning. |
| * <p/> |
| * This loader first tries to load values from a config file in SD card. Then it fills in missing |
| * values using constants and settings on the programming device. |
| */ |
| public class ProvisioningValuesLoader extends AsyncTaskLoader<Map<String, String>> { |
| |
| private static final String FILENAME = "nfcprovisioning.txt"; |
| private static final String TAG = "LoadProvisioningValuesTask"; |
| |
| private Map<String, String> mValues; |
| |
| public ProvisioningValuesLoader(Context context) { |
| super(context); |
| } |
| |
| @Override |
| public Map<String, String> loadInBackground() { |
| HashMap<String, String> values = new HashMap<>(); |
| loadFromDisk(values); |
| gatherAdminExtras(values); |
| loadSystemValues(values); |
| return values; |
| } |
| |
| @Override |
| public void deliverResult(Map<String, String> values) { |
| if (isReset()) { |
| return; |
| } |
| mValues = values; |
| super.deliverResult(values); |
| } |
| |
| @Override |
| protected void onStartLoading() { |
| if (mValues != null) { |
| deliverResult(mValues); |
| } |
| if (takeContentChanged() || mValues == null) { |
| forceLoad(); |
| } |
| } |
| |
| @Override |
| protected void onStopLoading() { |
| cancelLoad(); |
| } |
| |
| @Override |
| protected void onReset() { |
| super.onReset(); |
| onStopLoading(); |
| mValues = null; |
| } |
| |
| private void loadFromDisk(HashMap<String, String> values) { |
| File directory = Environment.getExternalStorageDirectory(); |
| File file = new File(directory, FILENAME); |
| if (!file.exists()) { |
| return; |
| } |
| Log.d(TAG, "Loading the config file..."); |
| try { |
| loadFromFile(values, file); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| Log.e(TAG, "Error loading data from " + file, e); |
| } |
| } |
| |
| private void loadFromFile(HashMap<String, String> values, File file) throws IOException { |
| BufferedReader reader = null; |
| try { |
| reader = new BufferedReader(new FileReader(file)); |
| String line; |
| while (null != (line = reader.readLine())) { |
| if (line.startsWith("#")) { |
| continue; |
| } |
| int position = line.indexOf("="); |
| if (position < 0) { // Not found |
| continue; |
| } |
| String key = line.substring(0, position); |
| String value = line.substring(position + 1); |
| values.put(key, value); |
| Log.d(TAG, key + "=" + value); |
| } |
| } finally { |
| if (reader != null) { |
| reader.close(); |
| } |
| } |
| } |
| |
| private void gatherAdminExtras(HashMap<String, String> values) { |
| HashMap<String, String> newMap = new HashMap<String, String>(); |
| Properties props = new Properties(); |
| Set<String>keys = new HashSet(values.keySet()); |
| for (String key : keys) { |
| if (key.startsWith("android.app.extra")) { |
| continue; |
| } |
| props.put(key, values.get(key)); |
| values.remove(key); |
| } |
| StringWriter sw = new StringWriter(); |
| try{ |
| props.store(sw, "admin extras bundle"); |
| values.put(DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, |
| sw.toString()); |
| Log.d(TAG, "Admin extras bundle=" + values.get( |
| DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE)); |
| } catch (IOException e) { |
| Log.e(TAG, "Unable to build admin extras bundle"); |
| } |
| } |
| |
| private void loadSystemValues(HashMap<String, String> values) { |
| Context context = getContext(); |
| putIfMissing(values, DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, |
| "com.example.android.deviceowner"); |
| putIfMissing(values, DevicePolicyManager.EXTRA_PROVISIONING_LOCALE, |
| context.getResources().getConfiguration().locale.toString()); |
| putIfMissing(values, DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE, |
| TimeZone.getDefault().getID()); |
| if (!values.containsKey(DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID)) { |
| WifiManager wifiManager = (WifiManager) context |
| .getSystemService(Activity.WIFI_SERVICE); |
| WifiInfo info = wifiManager.getConnectionInfo(); |
| values.put(DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID, trimSsid(info.getSSID())); |
| } |
| } |
| |
| /** |
| * {@link WifiInfo#getSSID} returns the WiFi SSID surrounded by double quotation marks. This |
| * method removes them if wifiSsid contains them. |
| */ |
| private static String trimSsid(String wifiSsid) { |
| int head = wifiSsid.startsWith("\"") ? 1 : 0; |
| int tail = wifiSsid.endsWith("\"") ? 1 : 0; |
| return wifiSsid.substring(head, wifiSsid.length() - tail); |
| } |
| |
| private static <Key, Value> void putIfMissing(HashMap<Key, Value> map, Key key, Value value) { |
| if (!map.containsKey(key)) { |
| map.put(key, value); |
| } |
| } |
| |
| } |