/*
|
* Copyright 2019 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.server.wifi;
|
|
import android.annotation.NonNull;
|
import android.annotation.Nullable;
|
import android.content.Context;
|
import android.net.IpMemoryStore;
|
import android.net.ipmemorystore.Blob;
|
import android.net.ipmemorystore.Status;
|
import android.util.Log;
|
|
import com.android.internal.util.Preconditions;
|
import com.android.server.wifi.WifiScoreCard.BlobListener;
|
|
import java.util.Objects;
|
|
/**
|
* Connects WifiScoreCard to IpMemoryStore.
|
*/
|
final class MemoryStoreImpl implements WifiScoreCard.MemoryStore {
|
private static final String TAG = "WifiMemoryStoreImpl";
|
private static final boolean DBG = true;
|
|
// The id of the client that stored this data
|
public static final String WIFI_FRAMEWORK_IP_MEMORY_STORE_CLIENT_ID = "com.android.server.wifi";
|
|
// The name of the data
|
public static final String WIFI_FRAMEWORK_IP_MEMORY_STORE_DATA_NAME = "scorecard.proto";
|
|
@NonNull private final Context mContext;
|
@NonNull private final WifiScoreCard mWifiScoreCard;
|
@NonNull private final WifiInjector mWifiInjector;
|
@Nullable private IpMemoryStore mIpMemoryStore;
|
|
MemoryStoreImpl(Context context, WifiInjector wifiInjector, WifiScoreCard wifiScoreCard) {
|
mContext = Preconditions.checkNotNull(context);
|
mWifiScoreCard = Preconditions.checkNotNull(wifiScoreCard);
|
mWifiInjector = Preconditions.checkNotNull(wifiInjector);
|
mIpMemoryStore = null;
|
}
|
|
private boolean mBroken = false;
|
private void handleException(Exception e) {
|
Log.wtf(TAG, "Exception using IpMemoryStore - disabling WifiScoreReport persistence", e);
|
mBroken = true;
|
}
|
|
|
@Override
|
public void read(final String key, final BlobListener blobListener) {
|
if (mBroken) return;
|
try {
|
mIpMemoryStore.retrieveBlob(
|
key,
|
WIFI_FRAMEWORK_IP_MEMORY_STORE_CLIENT_ID,
|
WIFI_FRAMEWORK_IP_MEMORY_STORE_DATA_NAME,
|
new CatchAFallingBlob(key, blobListener));
|
} catch (RuntimeException e) {
|
handleException(e);
|
}
|
}
|
|
/**
|
* Listens for a reply to a read request.
|
*
|
* Note that onBlobRetrieved() is called on a binder thread, so the
|
* provided blobListener must be prepared to deal with this.
|
*
|
*/
|
private static class CatchAFallingBlob
|
implements android.net.ipmemorystore.OnBlobRetrievedListener {
|
private final String mL2Key;
|
private final WifiScoreCard.BlobListener mBlobListener;
|
|
CatchAFallingBlob(String l2Key, WifiScoreCard.BlobListener blobListener) {
|
mL2Key = l2Key;
|
mBlobListener = blobListener;
|
}
|
|
@Override
|
public void onBlobRetrieved(Status status, String l2Key, String name, Blob data) {
|
if (!Objects.equals(mL2Key, l2Key)) {
|
throw new IllegalArgumentException("l2Key does not match request");
|
}
|
if (status.isSuccess()) {
|
if (data == null) {
|
if (DBG) Log.i(TAG, "Blob is null");
|
mBlobListener.onBlobRetrieved(null);
|
return;
|
}
|
mBlobListener.onBlobRetrieved(data.data);
|
} else {
|
if (DBG) Log.e(TAG, "android.net.ipmemorystore.Status " + status);
|
}
|
}
|
}
|
|
@Override
|
public void write(String key, byte[] value) {
|
if (mBroken) return;
|
final Blob blob = new Blob();
|
blob.data = value;
|
try {
|
mIpMemoryStore.storeBlob(
|
key,
|
WIFI_FRAMEWORK_IP_MEMORY_STORE_CLIENT_ID,
|
WIFI_FRAMEWORK_IP_MEMORY_STORE_DATA_NAME,
|
blob,
|
null /* no listener for now, just fire and forget */);
|
} catch (RuntimeException e) {
|
handleException(e);
|
}
|
}
|
|
/**
|
* Starts using IpMemoryStore.
|
*/
|
public void start() {
|
if (mIpMemoryStore != null) {
|
Log.w(TAG, "Reconnecting to IpMemoryStore service");
|
}
|
mIpMemoryStore = mWifiInjector.getIpMemoryStore();
|
if (mIpMemoryStore == null) {
|
Log.e(TAG, "No IpMemoryStore service!");
|
return;
|
}
|
mWifiScoreCard.installMemoryStore(this);
|
}
|
|
/**
|
* Stops using IpMemoryStore after performing any outstanding writes.
|
*/
|
public void stop() {
|
if (mIpMemoryStore == null) return;
|
mWifiScoreCard.doWrites();
|
// TODO - Should wait for writes to complete (or time out)
|
Log.i(TAG, "Disconnecting from IpMemoryStore service");
|
mIpMemoryStore = null;
|
}
|
|
}
|