Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve update kits performance #118

Merged
merged 1 commit into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void installReferrerUpdated() {
}
};

MParticle.getInstance().mKitManager = new KitFrameworkWrapper(mContext, null,null, null, null, true, null) {
MParticle.getInstance().mKitManager = new KitFrameworkWrapper(mContext, null,null, null, true, null) {
@Override
public void installReferrerUpdated() {
called[1] = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ public void logAll(List<? extends JsonReportingMessage> messageList) {
},
MParticle.getInstance().Internal().getConfigManager(),
MParticle.getInstance().Internal().getAppStateManager(),
com.mparticle.internal.AccessUtils.getUploadHandler(),
MParticleOptions.builder(mContext).credentials("some", "key").build());
this.latch = latch;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void onModifyCompleted(MParticleUser user, IdentityApiRequest request) {
static class StubKitManager extends KitFrameworkWrapper {

public StubKitManager(Context context) {
super(context, null, null, null, null, true, null);
super(context, null, null, null, true, null);
setKitManager(null);
}

Expand Down
36 changes: 17 additions & 19 deletions android-core/src/main/java/com/mparticle/MPServiceUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

import com.mparticle.internal.ConfigManager;
import com.mparticle.internal.Constants;
import com.mparticle.internal.KitFrameworkWrapper;
import com.mparticle.internal.KitsLoadedListener;
import com.mparticle.internal.KitsLoadedListenerConfiguration;
import com.mparticle.internal.Logger;
import com.mparticle.internal.KitsLoadedListener;
import com.mparticle.messaging.MPMessagingAPI;
import com.mparticle.messaging.ProviderCloudMessage;

Expand Down Expand Up @@ -149,28 +149,26 @@ private void handleNotificationTap(Intent intent) {
private void generateCloudMessage(final Intent intent) {
try {

KitsLoadedListener kitsLoadedListener = new KitsLoadedListener() {
@Override
public void onKitsLoaded() {
try {
MParticle instance = MParticle.getInstance();
if (instance != null) {
instance.Internal().getKitManager().loadKitLibrary();
ProviderCloudMessage cloudMessage = ProviderCloudMessage.createMessage(intent, ConfigManager.getPushKeys(mContext));
boolean handled = instance.Internal().getKitManager().onMessageReceived(mContext.getApplicationContext(), intent);
cloudMessage.setDisplayed(handled);
broadcastNotificationReceived(cloudMessage);
}
} catch (Exception e) {
Logger.warning("FCM parsing error: " + e.toString());
KitsLoadedListener kitsLoadedListener = () -> {
try {
MParticle instance = MParticle.getInstance();
if (instance != null) {
ProviderCloudMessage cloudMessage = ProviderCloudMessage.createMessage(intent, ConfigManager.getPushKeys(mContext));
boolean handled = instance.Internal().getKitManager().onMessageReceived(mContext.getApplicationContext(), intent);
cloudMessage.setDisplayed(handled);
broadcastNotificationReceived(cloudMessage);
}
} catch (Exception e) {
Logger.warning("FCM parsing error: " + e);
}
};
KitFrameworkWrapper.addKitsLoadedListener(kitsLoadedListener);
MParticle.start(MParticleOptions.builder(mContext).buildForInternalRestart());
MParticle.start(MParticleOptions
.builder(mContext)
.configuration(new KitsLoadedListenerConfiguration(kitsLoadedListener))
.buildForInternalRestart());

} catch (Exception e) {
Logger.warning("FCM parsing error: " + e.toString());
Logger.warning("FCM parsing error: " + e);
}
}

Expand Down
2 changes: 1 addition & 1 deletion android-core/src/main/java/com/mparticle/MParticle.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private static MParticle getInstance(@NonNull Context context, @NonNull MParticl
}

instance = new MParticle(options);
instance.mKitManager = new KitFrameworkWrapper(options.getContext(), instance.mMessageManager, instance.Internal().getConfigManager(), instance.Internal().getAppStateManager(), instance.mMessageManager.getTaskHandler(), options);
instance.mKitManager = new KitFrameworkWrapper(options.getContext(), instance.mMessageManager, instance.Internal().getConfigManager(), instance.Internal().getAppStateManager(), options);
instance.mIdentityApi = new IdentityApi(options.getContext(), instance.mInternal.getAppStateManager(), instance.mMessageManager, instance.mConfigManager, instance.mKitManager, options.getOperatingSystem());
instance.mMessageManager.refreshConfiguration();
instance.identify(options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;

import com.mparticle.Configuration;
import com.mparticle.ExceptionHandler;
Expand Down Expand Up @@ -176,6 +177,7 @@ private void restoreCoreConfig() {
* This called on startup. The only thing that's completely necessary is that we fire up kits.
*/
@Nullable
@WorkerThread
public JSONArray getLatestKitConfiguration() {
String oldConfig = getKitConfigPreferences().getString(KIT_CONFIG_KEY, new JSONArray().toString());
if (!MPUtility.isEmpty(oldConfig)) {
Expand Down Expand Up @@ -354,20 +356,12 @@ public synchronized void reloadCoreConfig(JSONObject responseJSON) throws JSONEx
updateCoreConfig(responseJSON, false);
}

private synchronized void reloadKitConfig(@Nullable JSONArray kitConfigs) {
//only reload if KitManager has not already been loaded (from new config, presumably)
MParticle instance = MParticle.getInstance();
if (instance != null ) {
instance.Internal().getKitManager().updateKits(kitConfigs);
onConfigLoaded(ConfigType.KIT, false);
}
}

private synchronized void updateKitConfig(@Nullable JSONArray kitConfigs) {
MParticle instance = MParticle.getInstance();
if (instance != null) {
instance.Internal().getKitManager().loadKitLibrary();
onConfigLoaded(ConfigType.KIT, true);
instance.Internal().getKitManager()
.updateKits(kitConfigs)
.onKitsLoaded(() -> onConfigLoaded(ConfigType.KIT, true));
}
}

Expand Down Expand Up @@ -474,7 +468,6 @@ public boolean getRestrictAAIDBasedOnLAT() {
* This method will be called from a background thread after startup is already complete.
*/
public void delayedStart() {
reloadKitConfig(getLatestKitConfiguration());
String senderId = getPushSenderId();
if (isPushEnabled() && senderId != null) {
MParticle.getInstance().Messaging().enablePushNotifications(senderId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import android.app.Activity;
import android.net.Uri;

import androidx.annotation.WorkerThread;

import com.mparticle.MParticleOptions;

import org.json.JSONArray;
Expand All @@ -17,14 +19,14 @@ public interface CoreCallbacks {
void setIntegrationAttributes(int kitId, Map<String, String> integrationAttributes);
Map<String, String> getIntegrationAttributes(int kitId);
WeakReference<Activity> getCurrentActivity();
@WorkerThread
JSONArray getLatestKitConfiguration();
MParticleOptions.DataplanOptions getDataplanOptions();
boolean isPushEnabled();
String getPushSenderId();
String getPushInstanceId();
Uri getLaunchUri();
String getLaunchAction();
void replayAndDisableQueue();
KitListener getKitListener();

interface KitListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;

import com.mparticle.AttributionResult;
import com.mparticle.BaseEvent;
Expand Down Expand Up @@ -35,7 +36,6 @@ public class KitFrameworkWrapper implements KitManager {
private final Context mContext;
final CoreCallbacks mCoreCallbacks;
private final ReportingManager mReportingManager;
private final BackgroundTaskHandler mBackgroundTaskHandler;
KitManager mKitManager;
private final MParticleOptions mOptions;
private volatile boolean frameworkLoadAttempted = false;
Expand All @@ -44,39 +44,47 @@ public class KitFrameworkWrapper implements KitManager {
private Queue eventQueue;
private Queue<AttributeChange> attributeQueue;
private volatile boolean registerForPush = false;
private static final List<KitsLoadedListener> kitsLoadedListeners = new ArrayList<KitsLoadedListener>();
private static final List<KitsLoadedListener> kitsLoadedListeners = new ArrayList<>();

public KitFrameworkWrapper(Context context, ReportingManager reportingManager, ConfigManager configManager, AppStateManager appStateManager, BackgroundTaskHandler backgroundTaskHandler, MParticleOptions options) {
this(context, reportingManager, configManager, appStateManager, backgroundTaskHandler, false, options);
public KitFrameworkWrapper(Context context, ReportingManager reportingManager, ConfigManager configManager, AppStateManager appStateManager, MParticleOptions options) {
this(context, reportingManager, configManager, appStateManager, false, options);
}

public KitFrameworkWrapper(Context context, ReportingManager reportingManager, ConfigManager configManager, AppStateManager appStateManager, BackgroundTaskHandler backgroundTaskHandler, boolean testing, MParticleOptions options) {
public KitFrameworkWrapper(Context context, ReportingManager reportingManager, ConfigManager configManager, AppStateManager appStateManager, boolean testing, MParticleOptions options) {
this.mOptions = options;
this.mContext = testing ? context : new KitContext(context);
this.mReportingManager = reportingManager;
this.mCoreCallbacks = new CoreCallbacksImpl(this, configManager, appStateManager);
this.mBackgroundTaskHandler = backgroundTaskHandler;
kitsLoaded = false;
}

@WorkerThread
public void loadKitLibrary() {
if (!frameworkLoadAttempted) {
Logger.debug("Loading Kit Framework.");
frameworkLoadAttempted = true;
try {
Class clazz = Class.forName("com.mparticle.kits.KitManagerImpl");
Constructor<KitFrameworkWrapper> constructor = clazz.getConstructor(Context.class, ReportingManager.class, CoreCallbacks.class, BackgroundTaskHandler.class, MParticleOptions.class);
mKitManager = constructor.newInstance(mContext, mReportingManager, mCoreCallbacks, mBackgroundTaskHandler, mOptions);
Constructor<KitFrameworkWrapper> constructor = clazz.getConstructor(Context.class, ReportingManager.class, CoreCallbacks.class, MParticleOptions.class);
KitManager kitManager = constructor.newInstance(mContext, mReportingManager, mCoreCallbacks, mOptions);
JSONArray configuration = mCoreCallbacks.getLatestKitConfiguration();
Logger.debug("Kit Framework loaded.");
if (configuration != null) {
if (!MPUtility.isEmpty(configuration)) {
Logger.debug("Restoring previous Kit configuration.");
updateKits(configuration);
kitManager
.updateKits(configuration)
.onKitsLoaded(() -> {
mKitManager = kitManager;
setKitsLoaded(true);
}
);
} else {
mKitManager = kitManager;
}
updateDataplan(mCoreCallbacks.getDataplanOptions());
} catch (Exception e) {
Logger.debug("No Kit Framework detected.");
disableQueuing();
setKitsLoaded(true);
}
}
}
Expand All @@ -97,21 +105,28 @@ void setKitManager(KitManager manager) {
mKitManager = manager;
}

public static boolean getKitsLoaded() {
public boolean getKitsLoaded() {
return kitsLoaded;
}

public static void addKitsLoadedListener(KitsLoadedListener listener) {
if (kitsLoaded) {
listener.onKitsLoaded();
} else {
kitsLoadedListeners.add(listener);
public void addKitsLoadedListener(KitsLoadedListener listener) {
if (listener != null) {
if (kitsLoaded) {
listener.onKitsLoaded();
} else {
kitsLoadedListeners.add(listener);
}
}
}

void setKitsLoaded(boolean kitsLoaded) {
this.kitsLoaded = kitsLoaded;
List<KitsLoadedListener> kitsLoadedListenersCopy = new ArrayList<KitsLoadedListener>(kitsLoadedListeners);
if (kitsLoaded) {
replayAndDisableQueue();
} else {
disableQueuing();
}
List<KitsLoadedListener> kitsLoadedListenersCopy = new ArrayList<>(kitsLoadedListeners);
for (KitsLoadedListener kitsLoadedListener: kitsLoadedListenersCopy) {
if (kitsLoadedListener != null) {
kitsLoadedListener.onKitsLoaded();
Expand All @@ -121,7 +136,6 @@ void setKitsLoaded(boolean kitsLoaded) {
}

synchronized void disableQueuing() {
setKitsLoaded(true);
if (eventQueue != null) {
eventQueue.clear();
eventQueue = null;
Expand Down Expand Up @@ -195,7 +209,6 @@ void replayEvents() {
}

synchronized public void replayAndDisableQueue() {
setKitsLoaded(true);
replayEvents();
disableQueuing();
}
Expand Down Expand Up @@ -461,10 +474,24 @@ public Set<Integer> getSupportedKits() {
}

@Override
public void updateKits(JSONArray kitConfiguration) {
public KitsLoadedCallback updateKits(JSONArray kitConfiguration) {
KitsLoadedCallback kitsLoadedCallback = new KitsLoadedCallback();
if (mKitManager != null) {
mKitManager.updateKits(kitConfiguration);
// we may have initialized the KitManagerImpl but didn't have a cached config to initialize
// any kits with. In this case, we will wait until this next config update to replay + disable queueing
if (!kitsLoaded) {
mKitManager
.updateKits(kitConfiguration)
.onKitsLoaded(() -> {
setKitsLoaded(true);
kitsLoadedCallback.setKitsLoaded();
}
);
} else {
return mKitManager.updateKits(kitConfiguration);
}
}
return kitsLoadedCallback;
}

@Override
Expand Down Expand Up @@ -693,11 +720,6 @@ public String getLaunchAction() {
return mAppStateManager.getLaunchAction();
}

@Override
public void replayAndDisableQueue() {
mKitFrameworkWrapper.replayAndDisableQueue();
}

@Override
public KitListener getKitListener() {
return kitListener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public interface KitManager {

Set<Integer> getSupportedKits();

void updateKits(JSONArray jsonArray);
KitsLoadedCallback updateKits(JSONArray jsonArray);

void updateDataplan(@NonNull MParticleOptions.DataplanOptions dataplanOptions);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.mparticle.internal

class KitsLoadedCallback {
@Volatile private var onKitsLoadedRunnable: OnKitManagerLoaded? = null
@Volatile private var loaded: Boolean = false

fun setKitsLoaded() {
synchronized(this) {
if (!loaded) {
loaded = true
onKitsLoadedRunnable?.onKitManagerLoaded()
}
}
}

fun onKitsLoaded(callback: OnKitManagerLoaded) {
synchronized(this) {
if (loaded) {
callback.onKitManagerLoaded()
} else {
onKitsLoadedRunnable = callback
}
}
}
}

interface OnKitManagerLoaded {
fun onKitManagerLoaded()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.mparticle.internal

import com.mparticle.Configuration

internal class KitsLoadedListenerConfiguration(private var kitsLoadedListener: KitsLoadedListener) : Configuration<KitFrameworkWrapper> {
override fun configures() = KitFrameworkWrapper::class.java
override fun apply(kitFrameworkWrapper: KitFrameworkWrapper) = kitFrameworkWrapper.addKitsLoadedListener(kitsLoadedListener)
}
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ public void refreshConfiguration() {
}

public void initConfigDelayed() {
mUploadHandler.sendEmptyMessageDelayed(UploadHandler.INIT_CONFIG, 1000);
mUploadHandler.sendEmptyMessageDelayed(UploadHandler.INIT_CONFIG, 10 * 1000);
}

@Override
Expand Down
Loading