559 lines
23 KiB
Java
559 lines
23 KiB
Java
/*
|
|
* Copyright (C) 2020 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 android.net.wifi;
|
|
|
|
import static android.os.Environment.getDataMiscCeDirectory;
|
|
import static android.os.Environment.getDataMiscDirectory;
|
|
|
|
import android.annotation.IntDef;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.SystemApi;
|
|
import android.content.Context;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
import android.os.UserHandle;
|
|
import android.provider.Settings;
|
|
import android.util.AtomicFile;
|
|
import android.util.SparseArray;
|
|
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.InputStream;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* Class used to provide one time hooks for existing OEM devices to migrate their config store
|
|
* data and other settings to the wifi apex.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public final class WifiMigration {
|
|
/**
|
|
* Directory to read the wifi config store files from under.
|
|
*/
|
|
private static final String LEGACY_WIFI_STORE_DIRECTORY_NAME = "wifi";
|
|
/**
|
|
* Config store file for general shared store file.
|
|
* AOSP Path on Android 10: /data/misc/wifi/WifiConfigStore.xml
|
|
*/
|
|
public static final int STORE_FILE_SHARED_GENERAL = 0;
|
|
/**
|
|
* Config store file for softap shared store file.
|
|
* AOSP Path on Android 10: /data/misc/wifi/softap.conf
|
|
*/
|
|
public static final int STORE_FILE_SHARED_SOFTAP = 1;
|
|
/**
|
|
* Config store file for general user store file.
|
|
* AOSP Path on Android 10: /data/misc_ce/<userId>/wifi/WifiConfigStore.xml
|
|
*/
|
|
public static final int STORE_FILE_USER_GENERAL = 2;
|
|
/**
|
|
* Config store file for network suggestions user store file.
|
|
* AOSP Path on Android 10: /data/misc_ce/<userId>/wifi/WifiConfigStoreNetworkSuggestions.xml
|
|
*/
|
|
public static final int STORE_FILE_USER_NETWORK_SUGGESTIONS = 3;
|
|
|
|
/** @hide */
|
|
@IntDef(prefix = { "STORE_FILE_SHARED_" }, value = {
|
|
STORE_FILE_SHARED_GENERAL,
|
|
STORE_FILE_SHARED_SOFTAP,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface SharedStoreFileId { }
|
|
|
|
/** @hide */
|
|
@IntDef(prefix = { "STORE_FILE_USER_" }, value = {
|
|
STORE_FILE_USER_GENERAL,
|
|
STORE_FILE_USER_NETWORK_SUGGESTIONS
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface UserStoreFileId { }
|
|
|
|
/**
|
|
* Mapping of Store file Id to Store file names.
|
|
*
|
|
* NOTE: This is the default path for the files on AOSP devices. If the OEM has modified
|
|
* the path or renamed the files, please edit this appropriately.
|
|
*/
|
|
private static final SparseArray<String> STORE_ID_TO_FILE_NAME =
|
|
new SparseArray<String>() {{
|
|
put(STORE_FILE_SHARED_GENERAL, "WifiConfigStore.xml");
|
|
put(STORE_FILE_SHARED_SOFTAP, "WifiConfigStoreSoftAp.xml");
|
|
put(STORE_FILE_USER_GENERAL, "WifiConfigStore.xml");
|
|
put(STORE_FILE_USER_NETWORK_SUGGESTIONS, "WifiConfigStoreNetworkSuggestions.xml");
|
|
}};
|
|
|
|
/**
|
|
* Pre-apex wifi shared folder.
|
|
*/
|
|
private static File getLegacyWifiSharedDirectory() {
|
|
return new File(getDataMiscDirectory(), LEGACY_WIFI_STORE_DIRECTORY_NAME);
|
|
}
|
|
|
|
/**
|
|
* Pre-apex wifi user folder.
|
|
*/
|
|
private static File getLegacyWifiUserDirectory(int userId) {
|
|
return new File(getDataMiscCeDirectory(userId), LEGACY_WIFI_STORE_DIRECTORY_NAME);
|
|
}
|
|
|
|
/**
|
|
* Legacy files were stored as AtomicFile. So, always use AtomicFile to operate on it to ensure
|
|
* data integrity.
|
|
*/
|
|
private static AtomicFile getSharedAtomicFile(@SharedStoreFileId int storeFileId) {
|
|
return new AtomicFile(new File(
|
|
getLegacyWifiSharedDirectory(),
|
|
STORE_ID_TO_FILE_NAME.get(storeFileId)));
|
|
}
|
|
|
|
/**
|
|
* Legacy files were stored as AtomicFile. So, always use AtomicFile to operate on it to ensure
|
|
* data integrity.
|
|
*/
|
|
private static AtomicFile getUserAtomicFile(@UserStoreFileId int storeFileId, int userId) {
|
|
return new AtomicFile(new File(
|
|
getLegacyWifiUserDirectory(userId),
|
|
STORE_ID_TO_FILE_NAME.get(storeFileId)));
|
|
}
|
|
|
|
private WifiMigration() { }
|
|
|
|
/**
|
|
* Load data from legacy shared wifi config store file.
|
|
* <p>
|
|
* Expected AOSP format is available in the sample files under {@code
|
|
* frameworks/base/wifi/non-updatable/migration_samples/}.
|
|
* </p>
|
|
* <p>
|
|
* Note:
|
|
* <li>OEMs need to change the implementation of
|
|
* {@link #convertAndRetrieveSharedConfigStoreFile(int)} only if their existing config store
|
|
* format or file locations differs from the vanilla AOSP implementation.</li>
|
|
* <li>The wifi apex will invoke
|
|
* {@link #convertAndRetrieveSharedConfigStoreFile(int)}
|
|
* method on every bootup, it is the responsibility of the OEM implementation to ensure that
|
|
* they perform the necessary in place conversion of their config store file to conform to the
|
|
* AOSP format. The OEM should ensure that the method should only return the
|
|
* {@link InputStream} stream for the data to be migrated only on the first bootup.</li>
|
|
* <li>Once the migration is done, the apex will invoke
|
|
* {@link #removeSharedConfigStoreFile(int)} to delete the store file.</li>
|
|
* <li>The only relevant invocation of {@link #convertAndRetrieveSharedConfigStoreFile(int)}
|
|
* occurs when a previously released device upgrades to the wifi apex from an OEM
|
|
* implementation of the wifi stack.
|
|
* <li>Ensure that the legacy file paths are accessible to the wifi module (sepolicy rules, file
|
|
* permissions, etc). Since the wifi service continues to run inside system_server process, this
|
|
* method will be called from the same context (so ideally the file should still be accessible).
|
|
* </li>
|
|
*
|
|
* @param storeFileId Identifier for the config store file. One of
|
|
* {@link #STORE_FILE_SHARED_GENERAL} or {@link #STORE_FILE_SHARED_GENERAL}
|
|
* @return Instance of {@link InputStream} for migrating data, null if no migration is
|
|
* necessary.
|
|
* @throws IllegalArgumentException on invalid storeFileId.
|
|
*/
|
|
@Nullable
|
|
public static InputStream convertAndRetrieveSharedConfigStoreFile(
|
|
@SharedStoreFileId int storeFileId) {
|
|
if (storeFileId != STORE_FILE_SHARED_GENERAL && storeFileId != STORE_FILE_SHARED_SOFTAP) {
|
|
throw new IllegalArgumentException("Invalid shared store file id");
|
|
}
|
|
try {
|
|
// OEMs should do conversions necessary here before returning the stream.
|
|
return getSharedAtomicFile(storeFileId).openRead();
|
|
} catch (FileNotFoundException e) {
|
|
// Special handling for softap.conf.
|
|
// Note: OEM devices upgrading from Q -> R will only have the softap.conf file.
|
|
// Test devices running previous R builds however may have already migrated to the
|
|
// XML format. So, check for that above before falling back to check for legacy file.
|
|
if (storeFileId == STORE_FILE_SHARED_SOFTAP) {
|
|
return SoftApConfToXmlMigrationUtil.convert();
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove the legacy shared wifi config store file.
|
|
*
|
|
* @param storeFileId Identifier for the config store file. One of
|
|
* {@link #STORE_FILE_SHARED_GENERAL} or {@link #STORE_FILE_SHARED_GENERAL}
|
|
* @throws IllegalArgumentException on invalid storeFileId.
|
|
*/
|
|
public static void removeSharedConfigStoreFile(@SharedStoreFileId int storeFileId) {
|
|
if (storeFileId != STORE_FILE_SHARED_GENERAL && storeFileId != STORE_FILE_SHARED_SOFTAP) {
|
|
throw new IllegalArgumentException("Invalid shared store file id");
|
|
}
|
|
AtomicFile file = getSharedAtomicFile(storeFileId);
|
|
if (file.exists()) {
|
|
file.delete();
|
|
return;
|
|
}
|
|
// Special handling for softap.conf.
|
|
// Note: OEM devices upgrading from Q -> R will only have the softap.conf file.
|
|
// Test devices running previous R builds however may have already migrated to the
|
|
// XML format. So, check for that above before falling back to check for legacy file.
|
|
if (storeFileId == STORE_FILE_SHARED_SOFTAP) {
|
|
SoftApConfToXmlMigrationUtil.remove();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load data from legacy user wifi config store file.
|
|
* <p>
|
|
* Expected AOSP format is available in the sample files under {@code
|
|
* frameworks/base/wifi/non-updatable/migration_samples/}.
|
|
* </p>
|
|
* <p>
|
|
* Note:
|
|
* <li>OEMs need to change the implementation of
|
|
* {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)} only if their existing config
|
|
* store format or file locations differs from the vanilla AOSP implementation.</li>
|
|
* <li>The wifi apex will invoke
|
|
* {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)}
|
|
* method on every bootup, it is the responsibility of the OEM implementation to ensure that
|
|
* they perform the necessary in place conversion of their config store file to conform to the
|
|
* AOSP format. The OEM should ensure that the method should only return the
|
|
* {@link InputStream} stream for the data to be migrated only on the first bootup.</li>
|
|
* <li>Once the migration is done, the apex will invoke
|
|
* {@link #removeUserConfigStoreFile(int, UserHandle)} to delete the store file.</li>
|
|
* <li>The only relevant invocation of
|
|
* {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)} occurs when a previously
|
|
* released device upgrades to the wifi apex from an OEM implementation of the wifi
|
|
* stack.
|
|
* </li>
|
|
* <li>Ensure that the legacy file paths are accessible to the wifi module (sepolicy rules, file
|
|
* permissions, etc). Since the wifi service continues to run inside system_server process, this
|
|
* method will be called from the same context (so ideally the file should still be accessible).
|
|
* </li>
|
|
*
|
|
* @param storeFileId Identifier for the config store file. One of
|
|
* {@link #STORE_FILE_USER_GENERAL} or {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}
|
|
* @param userHandle User handle.
|
|
* @return Instance of {@link InputStream} for migrating data, null if no migration is
|
|
* necessary.
|
|
* @throws IllegalArgumentException on invalid storeFileId or userHandle.
|
|
*/
|
|
@Nullable
|
|
public static InputStream convertAndRetrieveUserConfigStoreFile(
|
|
@UserStoreFileId int storeFileId, @NonNull UserHandle userHandle) {
|
|
if (storeFileId != STORE_FILE_USER_GENERAL
|
|
&& storeFileId != STORE_FILE_USER_NETWORK_SUGGESTIONS) {
|
|
throw new IllegalArgumentException("Invalid user store file id");
|
|
}
|
|
Objects.requireNonNull(userHandle);
|
|
try {
|
|
// OEMs should do conversions necessary here before returning the stream.
|
|
return getUserAtomicFile(storeFileId, userHandle.getIdentifier()).openRead();
|
|
} catch (FileNotFoundException e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove the legacy user wifi config store file.
|
|
*
|
|
* @param storeFileId Identifier for the config store file. One of
|
|
* {@link #STORE_FILE_USER_GENERAL} or {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}
|
|
* @param userHandle User handle.
|
|
* @throws IllegalArgumentException on invalid storeFileId or userHandle.
|
|
*/
|
|
public static void removeUserConfigStoreFile(
|
|
@UserStoreFileId int storeFileId, @NonNull UserHandle userHandle) {
|
|
if (storeFileId != STORE_FILE_USER_GENERAL
|
|
&& storeFileId != STORE_FILE_USER_NETWORK_SUGGESTIONS) {
|
|
throw new IllegalArgumentException("Invalid user store file id");
|
|
}
|
|
Objects.requireNonNull(userHandle);
|
|
AtomicFile file = getUserAtomicFile(storeFileId, userHandle.getIdentifier());
|
|
if (file.exists()) {
|
|
file.delete();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Container for all the wifi settings data to migrate.
|
|
*/
|
|
public static final class SettingsMigrationData implements Parcelable {
|
|
private final boolean mScanAlwaysAvailable;
|
|
private final boolean mP2pFactoryResetPending;
|
|
private final String mP2pDeviceName;
|
|
private final boolean mSoftApTimeoutEnabled;
|
|
private final boolean mWakeupEnabled;
|
|
private final boolean mScanThrottleEnabled;
|
|
private final boolean mVerboseLoggingEnabled;
|
|
|
|
private SettingsMigrationData(boolean scanAlwaysAvailable, boolean p2pFactoryResetPending,
|
|
@Nullable String p2pDeviceName, boolean softApTimeoutEnabled, boolean wakeupEnabled,
|
|
boolean scanThrottleEnabled, boolean verboseLoggingEnabled) {
|
|
mScanAlwaysAvailable = scanAlwaysAvailable;
|
|
mP2pFactoryResetPending = p2pFactoryResetPending;
|
|
mP2pDeviceName = p2pDeviceName;
|
|
mSoftApTimeoutEnabled = softApTimeoutEnabled;
|
|
mWakeupEnabled = wakeupEnabled;
|
|
mScanThrottleEnabled = scanThrottleEnabled;
|
|
mVerboseLoggingEnabled = verboseLoggingEnabled;
|
|
}
|
|
|
|
public static final @NonNull Parcelable.Creator<SettingsMigrationData> CREATOR =
|
|
new Parcelable.Creator<SettingsMigrationData>() {
|
|
@Override
|
|
public SettingsMigrationData createFromParcel(Parcel in) {
|
|
boolean scanAlwaysAvailable = in.readBoolean();
|
|
boolean p2pFactoryResetPending = in.readBoolean();
|
|
String p2pDeviceName = in.readString();
|
|
boolean softApTimeoutEnabled = in.readBoolean();
|
|
boolean wakeupEnabled = in.readBoolean();
|
|
boolean scanThrottleEnabled = in.readBoolean();
|
|
boolean verboseLoggingEnabled = in.readBoolean();
|
|
return new SettingsMigrationData(
|
|
scanAlwaysAvailable, p2pFactoryResetPending,
|
|
p2pDeviceName, softApTimeoutEnabled, wakeupEnabled,
|
|
scanThrottleEnabled, verboseLoggingEnabled);
|
|
}
|
|
|
|
@Override
|
|
public SettingsMigrationData[] newArray(int size) {
|
|
return new SettingsMigrationData[size];
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
|
dest.writeBoolean(mScanAlwaysAvailable);
|
|
dest.writeBoolean(mP2pFactoryResetPending);
|
|
dest.writeString(mP2pDeviceName);
|
|
dest.writeBoolean(mSoftApTimeoutEnabled);
|
|
dest.writeBoolean(mWakeupEnabled);
|
|
dest.writeBoolean(mScanThrottleEnabled);
|
|
dest.writeBoolean(mVerboseLoggingEnabled);
|
|
}
|
|
|
|
/**
|
|
* @return True if scans are allowed even when wifi is toggled off, false otherwise.
|
|
*/
|
|
public boolean isScanAlwaysAvailable() {
|
|
return mScanAlwaysAvailable;
|
|
}
|
|
|
|
/**
|
|
* @return indicate whether factory reset request is pending.
|
|
*/
|
|
public boolean isP2pFactoryResetPending() {
|
|
return mP2pFactoryResetPending;
|
|
}
|
|
|
|
/**
|
|
* @return the Wi-Fi peer-to-peer device name
|
|
*/
|
|
public @Nullable String getP2pDeviceName() {
|
|
return mP2pDeviceName;
|
|
}
|
|
|
|
/**
|
|
* @return Whether soft AP will shut down after a timeout period when no devices are
|
|
* connected.
|
|
*/
|
|
public boolean isSoftApTimeoutEnabled() {
|
|
return mSoftApTimeoutEnabled;
|
|
}
|
|
|
|
/**
|
|
* @return whether Wi-Fi Wakeup feature is enabled.
|
|
*/
|
|
public boolean isWakeUpEnabled() {
|
|
return mWakeupEnabled;
|
|
}
|
|
|
|
/**
|
|
* @return Whether wifi scan throttle is enabled or not.
|
|
*/
|
|
public boolean isScanThrottleEnabled() {
|
|
return mScanThrottleEnabled;
|
|
}
|
|
|
|
/**
|
|
* @return Whether to enable verbose logging in Wi-Fi.
|
|
*/
|
|
public boolean isVerboseLoggingEnabled() {
|
|
return mVerboseLoggingEnabled;
|
|
}
|
|
|
|
/**
|
|
* Builder to create instance of {@link SettingsMigrationData}.
|
|
*/
|
|
public static final class Builder {
|
|
private boolean mScanAlwaysAvailable;
|
|
private boolean mP2pFactoryResetPending;
|
|
private String mP2pDeviceName;
|
|
private boolean mSoftApTimeoutEnabled;
|
|
private boolean mWakeupEnabled;
|
|
private boolean mScanThrottleEnabled;
|
|
private boolean mVerboseLoggingEnabled;
|
|
|
|
public Builder() {
|
|
}
|
|
|
|
/**
|
|
* Setting to allow scans even when wifi is toggled off.
|
|
*
|
|
* @param available true if available, false otherwise.
|
|
* @return Instance of {@link Builder} to enable chaining of the builder method.
|
|
*/
|
|
public @NonNull Builder setScanAlwaysAvailable(boolean available) {
|
|
mScanAlwaysAvailable = available;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Indicate whether factory reset request is pending.
|
|
*
|
|
* @param pending true if pending, false otherwise.
|
|
* @return Instance of {@link Builder} to enable chaining of the builder method.
|
|
*/
|
|
public @NonNull Builder setP2pFactoryResetPending(boolean pending) {
|
|
mP2pFactoryResetPending = pending;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* The Wi-Fi peer-to-peer device name
|
|
*
|
|
* @param name Name if set, null otherwise.
|
|
* @return Instance of {@link Builder} to enable chaining of the builder method.
|
|
*/
|
|
public @NonNull Builder setP2pDeviceName(@Nullable String name) {
|
|
mP2pDeviceName = name;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Whether soft AP will shut down after a timeout period when no devices are connected.
|
|
*
|
|
* @param enabled true if enabled, false otherwise.
|
|
* @return Instance of {@link Builder} to enable chaining of the builder method.
|
|
*/
|
|
public @NonNull Builder setSoftApTimeoutEnabled(boolean enabled) {
|
|
mSoftApTimeoutEnabled = enabled;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Value to specify if Wi-Fi Wakeup feature is enabled.
|
|
*
|
|
* @param enabled true if enabled, false otherwise.
|
|
* @return Instance of {@link Builder} to enable chaining of the builder method.
|
|
*/
|
|
public @NonNull Builder setWakeUpEnabled(boolean enabled) {
|
|
mWakeupEnabled = enabled;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Whether wifi scan throttle is enabled or not.
|
|
*
|
|
* @param enabled true if enabled, false otherwise.
|
|
* @return Instance of {@link Builder} to enable chaining of the builder method.
|
|
*/
|
|
public @NonNull Builder setScanThrottleEnabled(boolean enabled) {
|
|
mScanThrottleEnabled = enabled;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Setting to enable verbose logging in Wi-Fi.
|
|
*
|
|
* @param enabled true if enabled, false otherwise.
|
|
* @return Instance of {@link Builder} to enable chaining of the builder method.
|
|
*/
|
|
public @NonNull Builder setVerboseLoggingEnabled(boolean enabled) {
|
|
mVerboseLoggingEnabled = enabled;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Build an instance of {@link SettingsMigrationData}.
|
|
*
|
|
* @return Instance of {@link SettingsMigrationData}.
|
|
*/
|
|
public @NonNull SettingsMigrationData build() {
|
|
return new SettingsMigrationData(mScanAlwaysAvailable, mP2pFactoryResetPending,
|
|
mP2pDeviceName, mSoftApTimeoutEnabled, mWakeupEnabled, mScanThrottleEnabled,
|
|
mVerboseLoggingEnabled);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load data from Settings.Global values.
|
|
*
|
|
* <p>
|
|
* Note:
|
|
* <li> This is method is invoked once on the first bootup. OEM can safely delete these settings
|
|
* once the migration is complete. The first & only relevant invocation of
|
|
* {@link #loadFromSettings(Context)} ()} occurs when a previously released
|
|
* device upgrades to the wifi apex from an OEM implementation of the wifi stack.
|
|
* </li>
|
|
*
|
|
* @param context Context to use for loading the settings provider.
|
|
* @return Instance of {@link SettingsMigrationData} for migrating data.
|
|
*/
|
|
@NonNull
|
|
public static SettingsMigrationData loadFromSettings(@NonNull Context context) {
|
|
if (Settings.Global.getInt(
|
|
context.getContentResolver(), Settings.Global.WIFI_MIGRATION_COMPLETED, 0) == 1) {
|
|
// migration already complete, ignore.
|
|
return null;
|
|
}
|
|
SettingsMigrationData data = new SettingsMigrationData.Builder()
|
|
.setScanAlwaysAvailable(
|
|
Settings.Global.getInt(context.getContentResolver(),
|
|
Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1)
|
|
.setP2pFactoryResetPending(
|
|
Settings.Global.getInt(context.getContentResolver(),
|
|
Settings.Global.WIFI_P2P_PENDING_FACTORY_RESET, 0) == 1)
|
|
.setP2pDeviceName(
|
|
Settings.Global.getString(context.getContentResolver(),
|
|
Settings.Global.WIFI_P2P_DEVICE_NAME))
|
|
.setSoftApTimeoutEnabled(
|
|
Settings.Global.getInt(context.getContentResolver(),
|
|
Settings.Global.SOFT_AP_TIMEOUT_ENABLED, 1) == 1)
|
|
.setWakeUpEnabled(
|
|
Settings.Global.getInt(context.getContentResolver(),
|
|
Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1)
|
|
.setScanThrottleEnabled(
|
|
Settings.Global.getInt(context.getContentResolver(),
|
|
Settings.Global.WIFI_SCAN_THROTTLE_ENABLED, 1) == 1)
|
|
.setVerboseLoggingEnabled(
|
|
Settings.Global.getInt(context.getContentResolver(),
|
|
Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0) == 1)
|
|
.build();
|
|
Settings.Global.putInt(
|
|
context.getContentResolver(), Settings.Global.WIFI_MIGRATION_COMPLETED, 1);
|
|
return data;
|
|
|
|
}
|
|
}
|