| /* |
| * 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; |
| } |
| |
| } |