All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.shadows.ShadowContextHubManager Maven / Gradle / Ivy

The newest version!
package org.robolectric.shadows;

import static org.robolectric.util.reflector.Reflector.reflector;

import android.app.PendingIntent;
import android.content.Context;
import android.hardware.location.ContextHubClient;
import android.hardware.location.ContextHubClientCallback;
import android.hardware.location.ContextHubInfo;
import android.hardware.location.ContextHubManager;
import android.hardware.location.ContextHubTransaction;
import android.hardware.location.NanoAppInstanceInfo;
import android.hardware.location.NanoAppMessage;
import android.hardware.location.NanoAppState;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import com.google.auto.value.AutoValue;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.robolectric.annotation.ClassName;
import org.robolectric.annotation.HiddenApi;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowContextHubClient.ContextHubClientReflector;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
import org.robolectric.util.reflector.Constructor;
import org.robolectric.util.reflector.ForType;

/** Shadow for {@link ContextHubManager}. */
@Implements(value = ContextHubManager.class, minSdk = VERSION_CODES.N, isInAndroidSdk = false)
public class ShadowContextHubManager {
  private static final List contextHubInfoList = new ArrayList<>();
  private static final List contextHubClientWithPendingIntentList =
      new ArrayList<>();
  private static final Map nanoAppUidToInfo =
      new ConcurrentHashMap<>();
  private static final Multimap contextHubToNanoappUid =
      Multimaps.synchronizedMultimap(HashMultimap.create());
  private static final Map nanoAppIdToInfo = new ConcurrentHashMap<>();
  private static final HashMultimap attributionTagToClientMap =
      HashMultimap.create();
  private static final Map
      contextHubClientCallbacks = new HashMap<>();

  static {
    contextHubInfoList.add(new ContextHubInfo());
  }

  /** Adds a nanoApp to the list of nanoApps that are supported by the provided contexthubinfo. */
  public void addNanoApp(ContextHubInfo info, int nanoAppUid, long nanoAppId, int nanoAppVersion) {
    contextHubToNanoappUid.put(info, nanoAppUid);
    NanoAppInstanceInfo instanceInfo =
        createInstanceInfo(info, nanoAppUid, nanoAppId, nanoAppVersion);
    nanoAppUidToInfo.put(nanoAppUid, instanceInfo);
    nanoAppIdToInfo.put(nanoAppId, info);
  }

  /** Creates and returns a {@link NanoAppInstanceInfo}. */
  public NanoAppInstanceInfo createInstanceInfo(
      ContextHubInfo info, int nanoAppUid, long nanoAppId, int nanoAppVersion) {
    if (VERSION.SDK_INT >= VERSION_CODES.P) {
      return new NanoAppInstanceInfo(nanoAppUid, nanoAppId, nanoAppVersion, info.getId());
    } else {
      NanoAppInstanceInfo instanceInfo = new NanoAppInstanceInfo();
      ReflectorNanoAppInstanceInfo reflectedInfo =
          reflector(ReflectorNanoAppInstanceInfo.class, instanceInfo);
      reflectedInfo.setAppId(nanoAppId);
      reflectedInfo.setAppVersion(nanoAppVersion);
      return instanceInfo;
    }
  }

  /**
   * Provides a list with fake {@link ContextHubInfo}s.
   *
   * 

{@link ContextHubInfo} describes an optional physical chip on the device. This does not * exist in test; this implementation allows to avoid possible NPEs. */ @Implementation(minSdk = VERSION_CODES.P) @HiddenApi protected List getContextHubs() { return contextHubInfoList; } @Implementation(minSdk = VERSION_CODES.P) @HiddenApi protected @ClassName("android.hardware.location.ContextHubClient") Object createClient( @ClassName("android.hardware.location.ContextHubInfo") Object contextHubInfo, @ClassName("android.hardware.location.ContextHubClientCallback") Object callback) { ContextHubClient client; if (Build.VERSION.SDK_INT >= VERSION_CODES.Q) { client = reflector(ContextHubClientReflector.class) .newContextHubClient((ContextHubInfo) contextHubInfo, false); } else { client = reflector(ContextHubClientReflector.class).newContextHubClient(); } if (callback != null) { contextHubClientCallbacks.put( client, ContextHubClientCallbackDetails.create( (ContextHubClientCallback) callback, MoreExecutors.directExecutor())); } return client; } @Implementation(minSdk = VERSION_CODES.P) @HiddenApi protected @ClassName("android.hardware.location.ContextHubClient") Object createClient( @ClassName("android.hardware.location.ContextHubInfo") Object contextHubInfo, @ClassName("android.hardware.location.ContextHubClientCallback") Object callback, Executor executor) { ContextHubClient client; if (Build.VERSION.SDK_INT >= VERSION_CODES.Q) { client = reflector(ContextHubClientReflector.class) .newContextHubClient((ContextHubInfo) contextHubInfo, false); } else { client = reflector(ContextHubClientReflector.class).newContextHubClient(); } if (callback != null) { contextHubClientCallbacks.put( client, ContextHubClientCallbackDetails.create((ContextHubClientCallback) callback, executor)); } return client; } @Implementation(minSdk = VERSION_CODES.Q) @HiddenApi protected @ClassName("android.hardware.location.ContextHubClient") Object createClient( @ClassName("android.hardware.location.ContextHubInfo") Object contextHubInfo, PendingIntent pendingIntent, long nanoAppId) { ContextHubClient client; if (Build.VERSION.SDK_INT >= VERSION_CODES.Q) { client = reflector(ContextHubClientReflector.class) .newContextHubClient((ContextHubInfo) contextHubInfo, false); } else { client = reflector(ContextHubClientReflector.class).newContextHubClient(); } contextHubClientWithPendingIntentList.add(client); return client; } @Implementation(minSdk = VERSION_CODES.S) @HiddenApi protected @ClassName("android.hardware.location.ContextHubClient") Object createClient( Context context, @ClassName("android.hardware.location.ContextHubInfo") Object contextHubInfo, Executor executor, @ClassName("android.hardware.location.ContextHubClientCallback") Object callback) { ContextHubClient client = reflector(ContextHubClientReflector.class) .newContextHubClient((ContextHubInfo) contextHubInfo, false); if (context != null && ((Context) context).getAttributionTag() != null) { attributionTagToClientMap.put(((Context) context).getAttributionTag(), client); } if (callback != null) { contextHubClientCallbacks.put( client, ContextHubClientCallbackDetails.create((ContextHubClientCallback) callback, executor)); } return client; } @Implementation(minSdk = VERSION_CODES.S) @HiddenApi protected @ClassName("android.hardware.location.ContextHubClient") Object createClient( Context context, ContextHubInfo contextHubInfo, PendingIntent pendingIntent, long nanoAppId) { ContextHubClient client = Shadow.newInstance( ContextHubClient.class, new Class[] {ContextHubInfo.class, Boolean.TYPE}, new Object[] {contextHubInfo, false}); contextHubClientWithPendingIntentList.add(client); return client; } @Implementation(minSdk = VERSION_CODES.S) @HiddenApi protected @ClassName("android.hardware.location.ContextHubTransaction") Object unloadNanoApp(ContextHubInfo contextHubInfo, long nanoAppId) { nanoAppIdToInfo.remove(nanoAppId); @SuppressWarnings("unchecked") ContextHubTransaction transaction = ReflectionHelpers.callConstructor( ContextHubTransaction.class, ClassParameter.from(int.class, ContextHubTransaction.TYPE_UNLOAD_NANOAPP)); // @SuppressWarnings("unchecked") ContextHubTransaction.Response> response = reflector(ReflectorContextHubTransactionResponse.class) .create(ContextHubTransaction.RESULT_SUCCESS, null); reflector(ReflectorContextHubTransaction.class, transaction).setResponse(response); return transaction; } @Nullable public List getClientsWithAttributionTag(String attributionTag) { return ImmutableList.copyOf(attributionTagToClientMap.get(attributionTag)); } @Nullable public List getContextHubClientWithPendingIntentList() { return ImmutableList.copyOf(contextHubClientWithPendingIntentList); } public void resetContextHub() { for (Map.Entry entry : contextHubClientCallbacks.entrySet()) { entry .getValue() .getExecutor() .execute(() -> entry.getValue().getCallback().onHubReset(entry.getKey())); } } public void broadcastMessageFromNanoApp(/*NanoAppMessage*/ Object message) { for (Map.Entry entry : contextHubClientCallbacks.entrySet()) { entry .getValue() .getExecutor() .execute( () -> entry .getValue() .getCallback() .onMessageFromNanoApp(entry.getKey(), (NanoAppMessage) message)); } } public void broadcastNanoAppAborted(long nanoAppId, int abortCode) { for (Map.Entry entry : contextHubClientCallbacks.entrySet()) { entry .getValue() .getExecutor() .execute( () -> entry .getValue() .getCallback() .onNanoAppAborted(entry.getKey(), nanoAppId, abortCode)); } } public void broadcastNanoAppLoaded(long nanoAppId) { for (Map.Entry entry : contextHubClientCallbacks.entrySet()) { entry .getValue() .getExecutor() .execute(() -> entry.getValue().getCallback().onNanoAppLoaded(entry.getKey(), nanoAppId)); } } public void broadcastNanoAppUnloaded(long nanoAppId) { for (Map.Entry entry : contextHubClientCallbacks.entrySet()) { entry .getValue() .getExecutor() .execute( () -> entry.getValue().getCallback().onNanoAppUnloaded(entry.getKey(), nanoAppId)); } } public void broadcastNanoAppEnabled(long nanoAppId) { for (Map.Entry entry : contextHubClientCallbacks.entrySet()) { entry .getValue() .getExecutor() .execute( () -> entry.getValue().getCallback().onNanoAppEnabled(entry.getKey(), nanoAppId)); } } public void broadcastNanoAppDisabled(long nanoAppId) { for (Map.Entry entry : contextHubClientCallbacks.entrySet()) { entry .getValue() .getExecutor() .execute( () -> entry.getValue().getCallback().onNanoAppDisabled(entry.getKey(), nanoAppId)); } } public void broadcastClientAuthorizationChanged(long nanoAppId, int authorization) { for (Map.Entry entry : contextHubClientCallbacks.entrySet()) { entry .getValue() .getExecutor() .execute( () -> entry .getValue() .getCallback() .onClientAuthorizationChanged(entry.getKey(), nanoAppId, authorization)); } } /** Returns true if the nanoapp is loaded. */ public boolean nanoAppIsLoaded(long nanoAppId) { return nanoAppIdToInfo.containsKey(nanoAppId); } @Resetter public static void clearContextHubClientWithPendingIntentList() { contextHubClientWithPendingIntentList.clear(); nanoAppUidToInfo.clear(); contextHubToNanoappUid.clear(); attributionTagToClientMap.clear(); contextHubClientCallbacks.clear(); nanoAppIdToInfo.clear(); } @Implementation(minSdk = VERSION_CODES.P) @HiddenApi protected @ClassName( "android.hardware.location.ContextHubTransaction>") Object queryNanoApps(ContextHubInfo contextHubInfo) { @SuppressWarnings("unchecked") ContextHubTransaction> transaction = ReflectionHelpers.callConstructor( ContextHubTransaction.class, ClassParameter.from(int.class, ContextHubTransaction.TYPE_QUERY_NANOAPPS)); Collection uids = contextHubToNanoappUid.get(contextHubInfo); List nanoAppStates = new ArrayList<>(); for (Integer uid : uids) { NanoAppInstanceInfo info = nanoAppUidToInfo.get(uid); if (info != null) { nanoAppStates.add( new NanoAppState(info.getAppId(), info.getAppVersion(), true /* enabled */)); } } ContextHubTransaction.Response> response = reflector(ReflectorContextHubTransactionResponse.class) .create(ContextHubTransaction.RESULT_SUCCESS, nanoAppStates); reflector(ReflectorContextHubTransaction.class, transaction).setResponse(response); return transaction; } /** * Provides an array of fake handles. * *

These describe an optional physical chip on the device which does not exist during testing. * This implementation enables testing of classes that utilize these APIs. */ @Implementation @HiddenApi protected int[] getContextHubHandles() { int[] handles = new int[contextHubInfoList.size()]; for (int i = 0; i < handles.length; i++) { handles[i] = i; } return handles; } @Implementation @HiddenApi protected ContextHubInfo getContextHubInfo(int hubHandle) { if (hubHandle < 0 || hubHandle >= contextHubInfoList.size()) { return null; } return contextHubInfoList.get(hubHandle); } @Implementation @HiddenApi protected NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) { return nanoAppUidToInfo.get(nanoAppHandle); } @AutoValue abstract static class ContextHubClientCallbackDetails { @Nonnull abstract ContextHubClientCallback getCallback(); @Nonnull abstract Executor getExecutor(); static ContextHubClientCallbackDetails create( ContextHubClientCallback callback, Executor executor) { return new AutoValue_ShadowContextHubManager_ContextHubClientCallbackDetails( callback, executor); } } /** Accessor interface for {@link NanoAppInstanceInfo}'s internals. */ @ForType(NanoAppInstanceInfo.class) private interface ReflectorNanoAppInstanceInfo { void setAppId(long nanoAppId); void setAppVersion(int nanoAppVersion); } /** Accessor interface for {@link ContextHubTransaction}'s internals. */ @ForType(ContextHubTransaction.class) private interface ReflectorContextHubTransaction { void setResponse(ContextHubTransaction.Response> response); } /** Accessor interface for {@link ContextHubTransaction.Response}'s internals. */ @ForType(ContextHubTransaction.Response.class) private interface ReflectorContextHubTransactionResponse { @Constructor ContextHubTransaction.Response> create(int result, Object contents); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy