1 /* 2 * Copyright (C) 2014 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.server.ethernet; 18 19 import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME; 20 21 import android.annotation.Nullable; 22 import android.content.ApexEnvironment; 23 import android.net.IpConfiguration; 24 import android.os.Environment; 25 import android.util.ArrayMap; 26 import android.util.AtomicFile; 27 import android.util.Log; 28 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.server.net.IpConfigStore; 31 32 import java.io.File; 33 import java.io.FileOutputStream; 34 import java.io.IOException; 35 36 /** 37 * This class provides an API to store and manage Ethernet network configuration. 38 */ 39 public class EthernetConfigStore { 40 private static final String TAG = EthernetConfigStore.class.getSimpleName(); 41 private static final String CONFIG_FILE = "ipconfig.txt"; 42 private static final String FILE_PATH = "/misc/ethernet/"; 43 private static final String LEGACY_IP_CONFIG_FILE_PATH = Environment.getDataDirectory() 44 + FILE_PATH; 45 private static final String APEX_IP_CONFIG_FILE_PATH = ApexEnvironment.getApexEnvironment( 46 TETHERING_MODULE_NAME).getDeviceProtectedDataDir() + FILE_PATH; 47 48 private IpConfigStore mStore = new IpConfigStore(); 49 private final ArrayMap<String, IpConfiguration> mIpConfigurations; 50 private IpConfiguration mIpConfigurationForDefaultInterface; 51 private final Object mSync = new Object(); 52 EthernetConfigStore()53 public EthernetConfigStore() { 54 mIpConfigurations = new ArrayMap<>(0); 55 } 56 doesConfigFileExist(final String filepath)57 private static boolean doesConfigFileExist(final String filepath) { 58 return new File(filepath).exists(); 59 } 60 writeLegacyIpConfigToApexPath(final String newFilePath, final String oldFilePath, final String filename)61 private void writeLegacyIpConfigToApexPath(final String newFilePath, final String oldFilePath, 62 final String filename) { 63 final File directory = new File(newFilePath); 64 if (!directory.exists()) { 65 directory.mkdirs(); 66 } 67 68 // Write the legacy IP config to the apex file path. 69 FileOutputStream fos = null; 70 final AtomicFile dst = new AtomicFile(new File(newFilePath + filename)); 71 final AtomicFile src = new AtomicFile(new File(oldFilePath + filename)); 72 try { 73 final byte[] raw = src.readFully(); 74 if (raw.length > 0) { 75 fos = dst.startWrite(); 76 fos.write(raw); 77 fos.flush(); 78 dst.finishWrite(fos); 79 } 80 } catch (IOException e) { 81 Log.e(TAG, "Fail to sync the legacy IP config to the apex file path."); 82 dst.failWrite(fos); 83 } 84 } 85 read()86 public void read() { 87 read(APEX_IP_CONFIG_FILE_PATH, LEGACY_IP_CONFIG_FILE_PATH, CONFIG_FILE); 88 } 89 90 @VisibleForTesting read(final String newFilePath, final String oldFilePath, final String filename)91 void read(final String newFilePath, final String oldFilePath, final String filename) { 92 synchronized (mSync) { 93 // Attempt to read the IP configuration from apex file path first. 94 if (doesConfigFileExist(newFilePath + filename)) { 95 loadConfigFileLocked(newFilePath + filename); 96 return; 97 } 98 99 // If the config file doesn't exist in the apex file path, attempt to read it from 100 // the legacy file path, if config file exists, write the legacy IP configuration to 101 // apex config file path, this should just happen on the first boot. New or updated 102 // config entries are only written to the apex config file later. 103 if (!doesConfigFileExist(oldFilePath + filename)) return; 104 loadConfigFileLocked(oldFilePath + filename); 105 writeLegacyIpConfigToApexPath(newFilePath, oldFilePath, filename); 106 } 107 } 108 loadConfigFileLocked(final String filepath)109 private void loadConfigFileLocked(final String filepath) { 110 final ArrayMap<String, IpConfiguration> configs = 111 IpConfigStore.readIpConfigurations(filepath); 112 mIpConfigurations.putAll(configs); 113 } 114 write(String iface, IpConfiguration config)115 public void write(String iface, IpConfiguration config) { 116 write(iface, config, APEX_IP_CONFIG_FILE_PATH + CONFIG_FILE); 117 } 118 119 @VisibleForTesting write(String iface, IpConfiguration config, String filepath)120 void write(String iface, IpConfiguration config, String filepath) { 121 boolean modified; 122 123 synchronized (mSync) { 124 if (config == null) { 125 modified = mIpConfigurations.remove(iface) != null; 126 } else { 127 IpConfiguration oldConfig = mIpConfigurations.put(iface, config); 128 modified = !config.equals(oldConfig); 129 } 130 131 if (modified) { 132 mStore.writeIpConfigurations(filepath, mIpConfigurations); 133 } 134 } 135 } 136 getIpConfigurations()137 public ArrayMap<String, IpConfiguration> getIpConfigurations() { 138 synchronized (mSync) { 139 return new ArrayMap<>(mIpConfigurations); 140 } 141 } 142 143 @Nullable getIpConfigurationForDefaultInterface()144 public IpConfiguration getIpConfigurationForDefaultInterface() { 145 return null; 146 } 147 } 148