<commit_before>package com.smartdevicelink.api.lockscreen;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.util.Log;

import com.smartdevicelink.api.BaseSubManager;
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCNotification;
import com.smartdevicelink.proxy.interfaces.ISdl;
import com.smartdevicelink.proxy.rpc.OnDriverDistraction;
import com.smartdevicelink.proxy.rpc.OnHMIStatus;
import com.smartdevicelink.proxy.rpc.OnSystemRequest;
import com.smartdevicelink.proxy.rpc.enums.DriverDistractionState;
import com.smartdevicelink.proxy.rpc.enums.HMILevel;
import com.smartdevicelink.proxy.rpc.enums.LockScreenStatus;
import com.smartdevicelink.proxy.rpc.enums.RequestType;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
import com.smartdevicelink.util.HttpUtils;

import org.json.JSONException;

import java.io.IOException;
import java.lang.ref.WeakReference;

/**
 * <strong>LockscreenManager</strong> <br>
 *
 * Note: This class must be accessed through the SdlManager. Do not instantiate it by itself. <br>
 *
 * The LockscreenManager handles the logic of showing and hiding the lock screen. <br>
 *
 */
public class LockScreenManager extends BaseSubManager {

	private static final String TAG = "LockScreenManager";
	private WeakReference<Context> context;
	private HMILevel hmiLevel;
	private boolean isAppInUse, driverDistStatus, lockScreenEnabled, showOEMLogo;
	private int lockScreenIcon, lockscreenColor, customView;
	private OnRPCNotificationListener systemRequestListener, ddListener, hmiListener;
	private String OEMIconUrl;
	private Bitmap lockScreenOEMIcon;

	public LockScreenManager(LockScreenConfig lockScreenConfig, Context context, ISdl internalInterface){

		super(internalInterface);
		this.context = new WeakReference<>(context);

		// set initial class variables
		hmiLevel = HMILevel.HMI_NONE;
		isAppInUse = false;
		driverDistStatus = false;

		// setup the manager
		readConfiguration(lockScreenConfig);
		setupListeners();

		// transition state
		transitionToState(READY);
	}

	@Override
	public void dispose(){
		// remove listeners
		internalInterface.removeOnRPCNotificationListener(FunctionID.ON_SYSTEM_REQUEST, systemRequestListener);
		internalInterface.removeOnRPCNotificationListener(FunctionID.ON_DRIVER_DISTRACTION, ddListener);
		internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener);

		// transition state
		transitionToState(SHUTDOWN);
	}

	////
	// SETUP
	////

	/**
	 * Reads configuration set in SDLManager Builder
	 * @param lockScreenConfig - the configuration set.
	 */
	private void readConfiguration(LockScreenConfig lockScreenConfig){
		lockScreenIcon = lockScreenConfig.getAppIcon();
		lockscreenColor = lockScreenConfig.getBackgroundColor();
		customView = lockScreenConfig.getCustomView();
		lockScreenEnabled = lockScreenConfig.getEnabled();
		showOEMLogo = lockScreenConfig.getShowOEMLogo();
	}

	/**
	 * Adds 3 listeners that help determine whether or not a lockscreen should be shown.
	 * This will change the variables that we hold in the manager to the newest values and then
	 * usually call launchLockScreenActivity
	 *
	 * 1. ON_HMI_STATUS
	 * 2. ON_DRIVER_DISTRACTION
	 * 3. ON_SYSTEM_REQUEST (used for OEM Icon Downloading)
	 */
	private void setupListeners(){
		// add hmi listener
		hmiListener = new OnRPCNotificationListener() {
			@Override
			public void onNotified(RPCNotification notification) {
				hmiLevel = ((OnHMIStatus)notification).getHmiLevel();
				if (hmiLevel.equals(HMILevel.HMI_FULL) || hmiLevel.equals(HMILevel.HMI_LIMITED)){
					Log.i(TAG, "HMI Notification APP_IN_USE True");
					isAppInUse = true;
				}else{
					Log.i(TAG, "HMI Notification APP_IN_USE False");
					isAppInUse = false;
				}
				launchLockScreenActivity();
			}
		};
		internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener);

		// set up driver distraction listener
		ddListener = new OnRPCNotificationListener() {
			@Override
			public void onNotified(RPCNotification notification) {
				// do something with the status
				if (notification != null) {
					OnDriverDistraction ddState = (OnDriverDistraction) notification;

					if (ddState.getState() == DriverDistractionState.DD_ON){
						Log.i(TAG, "DD On Notification");
						// launch lock screen
						driverDistStatus = true;
						launchLockScreenActivity();
					}else{
						Log.i(TAG, "DD Off Notification");
						// close lock screen
						driverDistStatus = false;
						context.get().sendBroadcast(new Intent(SDLLockScreenActivity.CLOSE_LOCK_SCREEN_ACTION));
					}
				}
			}
		};
		internalInterface.addOnRPCNotificationListener(FunctionID.ON_DRIVER_DISTRACTION, ddListener);

		// set up system request listener
		systemRequestListener = new OnRPCNotificationListener() {
			@Override
			public void onNotified(RPCNotification notification) {
				// do something with the status
				final OnSystemRequest msg = (OnSystemRequest) notification;
				try {
					Log.i(TAG, "SYSTEM REQUEST: "+ notification.serializeJSON().toString());
				} catch (JSONException e) {
					e.printStackTrace();
				}
				if (msg.getRequestType() == RequestType.LOCK_SCREEN_ICON_URL &&
						msg.getUrl() != null) {
					// send intent to activity to download icon from core
					Log.i(TAG, "SYSTEM REQUEST - ICON Ready for Download");
					OEMIconUrl = msg.getUrl();
					downloadLockScreenIcon(OEMIconUrl);
				}
			}
		};
		internalInterface.addOnRPCNotificationListener(FunctionID.ON_SYSTEM_REQUEST, systemRequestListener);
	}

	////
	// LAUNCH LOCK SCREEN LOGIC
	////

	/**
	 * 1. Check if user wants us to manage lock screen
	 * 2. If so, get the HMI level and LockScreenStatus from the method below
	 * 3. Build intent and start the SDLLockScreenActivity
	 *
	 * X. If the status is set to OFF, Send broadcast to close lock screen if it is open
	 */
	private void launchLockScreenActivity(){
		// intent to open SDLLockScreenActivity
		// pass in icon, background color, and custom view
		if (lockScreenEnabled) {
			LockScreenStatus status = getLockScreenStatus();
			if (hmiLevel == HMILevel.HMI_FULL && status == LockScreenStatus.REQUIRED) {
				Intent showLockScreenIntent = new Intent(context.get(), SDLLockScreenActivity.class);
				showLockScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

				// Extra parameters for customization of the lock screen view
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_ICON_EXTRA, lockScreenIcon);
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_COLOR_EXTRA, lockscreenColor);
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_CUSTOM_VIEW_EXTRA, customView);
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_OEM_ICON_EXTRA, showOEMLogo);
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_OEM_ICON_BITMAP, lockScreenOEMIcon);

				context.get().startActivity(showLockScreenIntent);
			} else if (status == LockScreenStatus.OFF) {
				context.get().sendBroadcast(new Intent(SDLLockScreenActivity.CLOSE_LOCK_SCREEN_ACTION));
			}
		}
	}

	////
	// HELPERS
	////

	/**
	 * Step through some logic to determine if we need to show the lock screen or not
	 * This function is usually triggered on some sort of notification.
	 *
	 * @return Whether or not the Lock Screen is required
	 */
	private synchronized LockScreenStatus getLockScreenStatus() {

		if ( (hmiLevel == null) || (hmiLevel.equals(HMILevel.HMI_NONE))) {
			return LockScreenStatus.OFF;
		}
		else if ( hmiLevel.equals(HMILevel.HMI_BACKGROUND)) {
			if (!driverDistStatus) {
				//we don't have driver distraction, lock screen is entirely based on if user is using the app on the head unit
				if (isAppInUse) {
					return LockScreenStatus.REQUIRED;
				} else {
					return LockScreenStatus.OFF;
				}
			}
			else if (isAppInUse) {
				return LockScreenStatus.REQUIRED;
			} else {
				return LockScreenStatus.OFF;
			}
		}
		else if ( (hmiLevel.equals(HMILevel.HMI_FULL)) || (hmiLevel.equals(HMILevel.HMI_LIMITED))) {
			if (!driverDistStatus) {
				return LockScreenStatus.OPTIONAL;
			} else {
				return LockScreenStatus.REQUIRED;
			}
		}
		return LockScreenStatus.OFF;
	}

	private void downloadLockScreenIcon(final String url){
		new Thread(new Runnable(){
			@Override
			public void run(){
				try{
					lockScreenOEMIcon = HttpUtils.downloadImage(url);
					Log.i(TAG, "Lock Screen Icon Downloaded");
				}catch(IOException e){
					Log.e(TAG, "Lock Screen Icon Error Downloading");
				}
			}
		}).start();
	}

}
<commit_msg>clear icon reference on destruction. ready for unit tests<commit_after>package com.smartdevicelink.api.lockscreen;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.util.Log;

import com.smartdevicelink.api.BaseSubManager;
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCNotification;
import com.smartdevicelink.proxy.interfaces.ISdl;
import com.smartdevicelink.proxy.rpc.OnDriverDistraction;
import com.smartdevicelink.proxy.rpc.OnHMIStatus;
import com.smartdevicelink.proxy.rpc.OnSystemRequest;
import com.smartdevicelink.proxy.rpc.enums.DriverDistractionState;
import com.smartdevicelink.proxy.rpc.enums.HMILevel;
import com.smartdevicelink.proxy.rpc.enums.LockScreenStatus;
import com.smartdevicelink.proxy.rpc.enums.RequestType;
import com.smartdevicelink.proxy.rpc.listeners.OnRPCNotificationListener;
import com.smartdevicelink.util.HttpUtils;

import org.json.JSONException;

import java.io.IOException;
import java.lang.ref.WeakReference;

/**
 * <strong>LockscreenManager</strong> <br>
 *
 * Note: This class must be accessed through the SdlManager. Do not instantiate it by itself. <br>
 *
 * The LockscreenManager handles the logic of showing and hiding the lock screen. <br>
 *
 */
public class LockScreenManager extends BaseSubManager {

	private static final String TAG = "LockScreenManager";
	private WeakReference<Context> context;
	private HMILevel hmiLevel;
	private boolean isAppInUse, driverDistStatus, lockScreenEnabled, showOEMLogo;
	private int lockScreenIcon, lockscreenColor, customView;
	private OnRPCNotificationListener systemRequestListener, ddListener, hmiListener;
	private String OEMIconUrl;
	private Bitmap lockScreenOEMIcon;

	public LockScreenManager(LockScreenConfig lockScreenConfig, Context context, ISdl internalInterface){

		super(internalInterface);
		this.context = new WeakReference<>(context);

		// set initial class variables
		hmiLevel = HMILevel.HMI_NONE;
		isAppInUse = false;
		driverDistStatus = false;

		// setup the manager
		readConfiguration(lockScreenConfig);
		setupListeners();

		// transition state
		transitionToState(READY);
	}

	@Override
	public void dispose(){
		// remove listeners
		internalInterface.removeOnRPCNotificationListener(FunctionID.ON_SYSTEM_REQUEST, systemRequestListener);
		internalInterface.removeOnRPCNotificationListener(FunctionID.ON_DRIVER_DISTRACTION, ddListener);
		internalInterface.removeOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener);
		lockScreenOEMIcon = null;
		OEMIconUrl = null;

		// transition state
		transitionToState(SHUTDOWN);
	}

	////
	// SETUP
	////

	/**
	 * Reads configuration set in SDLManager Builder
	 * @param lockScreenConfig - the configuration set.
	 */
	private void readConfiguration(LockScreenConfig lockScreenConfig){
		lockScreenIcon = lockScreenConfig.getAppIcon();
		lockscreenColor = lockScreenConfig.getBackgroundColor();
		customView = lockScreenConfig.getCustomView();
		lockScreenEnabled = lockScreenConfig.getEnabled();
		showOEMLogo = lockScreenConfig.getShowOEMLogo();
	}

	/**
	 * Adds 3 listeners that help determine whether or not a lockscreen should be shown.
	 * This will change the variables that we hold in the manager to the newest values and then
	 * usually call launchLockScreenActivity
	 *
	 * 1. ON_HMI_STATUS
	 * 2. ON_DRIVER_DISTRACTION
	 * 3. ON_SYSTEM_REQUEST (used for OEM Icon Downloading)
	 */
	private void setupListeners(){
		// add hmi listener
		hmiListener = new OnRPCNotificationListener() {
			@Override
			public void onNotified(RPCNotification notification) {
				hmiLevel = ((OnHMIStatus)notification).getHmiLevel();
				if (hmiLevel.equals(HMILevel.HMI_FULL) || hmiLevel.equals(HMILevel.HMI_LIMITED)){
					Log.i(TAG, "HMI Notification APP_IN_USE True");
					isAppInUse = true;
				}else{
					Log.i(TAG, "HMI Notification APP_IN_USE False");
					isAppInUse = false;
				}
				launchLockScreenActivity();
			}
		};
		internalInterface.addOnRPCNotificationListener(FunctionID.ON_HMI_STATUS, hmiListener);

		// set up driver distraction listener
		ddListener = new OnRPCNotificationListener() {
			@Override
			public void onNotified(RPCNotification notification) {
				// do something with the status
				if (notification != null) {
					OnDriverDistraction ddState = (OnDriverDistraction) notification;

					if (ddState.getState() == DriverDistractionState.DD_ON){
						Log.i(TAG, "DD On Notification");
						// launch lock screen
						driverDistStatus = true;
						launchLockScreenActivity();
					}else{
						Log.i(TAG, "DD Off Notification");
						// close lock screen
						driverDistStatus = false;
						context.get().sendBroadcast(new Intent(SDLLockScreenActivity.CLOSE_LOCK_SCREEN_ACTION));
					}
				}
			}
		};
		internalInterface.addOnRPCNotificationListener(FunctionID.ON_DRIVER_DISTRACTION, ddListener);

		// set up system request listener
		systemRequestListener = new OnRPCNotificationListener() {
			@Override
			public void onNotified(RPCNotification notification) {
				// do something with the status
				final OnSystemRequest msg = (OnSystemRequest) notification;
				try {
					Log.i(TAG, "SYSTEM REQUEST: "+ notification.serializeJSON().toString());
				} catch (JSONException e) {
					e.printStackTrace();
				}
				if (msg.getRequestType() == RequestType.LOCK_SCREEN_ICON_URL &&
						msg.getUrl() != null) {
					// send intent to activity to download icon from core
					Log.i(TAG, "SYSTEM REQUEST - ICON Ready for Download");
					OEMIconUrl = msg.getUrl();
					downloadLockScreenIcon(OEMIconUrl);
				}
			}
		};
		internalInterface.addOnRPCNotificationListener(FunctionID.ON_SYSTEM_REQUEST, systemRequestListener);
	}

	////
	// LAUNCH LOCK SCREEN LOGIC
	////

	/**
	 * 1. Check if user wants us to manage lock screen
	 * 2. If so, get the HMI level and LockScreenStatus from the method below
	 * 3. Build intent and start the SDLLockScreenActivity
	 *
	 * X. If the status is set to OFF, Send broadcast to close lock screen if it is open
	 */
	private void launchLockScreenActivity(){
		// intent to open SDLLockScreenActivity
		// pass in icon, background color, and custom view
		if (lockScreenEnabled) {
			LockScreenStatus status = getLockScreenStatus();
			if (hmiLevel == HMILevel.HMI_FULL && status == LockScreenStatus.REQUIRED) {
				Intent showLockScreenIntent = new Intent(context.get(), SDLLockScreenActivity.class);
				showLockScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

				// Extra parameters for customization of the lock screen view
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_ICON_EXTRA, lockScreenIcon);
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_COLOR_EXTRA, lockscreenColor);
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_CUSTOM_VIEW_EXTRA, customView);
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_OEM_ICON_EXTRA, showOEMLogo);
				showLockScreenIntent.putExtra(SDLLockScreenActivity.LOCKSCREEN_OEM_ICON_BITMAP, lockScreenOEMIcon);

				context.get().startActivity(showLockScreenIntent);
			} else if (status == LockScreenStatus.OFF) {
				context.get().sendBroadcast(new Intent(SDLLockScreenActivity.CLOSE_LOCK_SCREEN_ACTION));
			}
		}
	}

	////
	// HELPERS
	////

	/**
	 * Step through some logic to determine if we need to show the lock screen or not
	 * This function is usually triggered on some sort of notification.
	 *
	 * @return Whether or not the Lock Screen is required
	 */
	private synchronized LockScreenStatus getLockScreenStatus() {

		if ( (hmiLevel == null) || (hmiLevel.equals(HMILevel.HMI_NONE))) {
			return LockScreenStatus.OFF;
		}
		else if ( hmiLevel.equals(HMILevel.HMI_BACKGROUND)) {
			if (!driverDistStatus) {
				//we don't have driver distraction, lock screen is entirely based on if user is using the app on the head unit
				if (isAppInUse) {
					return LockScreenStatus.REQUIRED;
				} else {
					return LockScreenStatus.OFF;
				}
			}
			else if (isAppInUse) {
				return LockScreenStatus.REQUIRED;
			} else {
				return LockScreenStatus.OFF;
			}
		}
		else if ( (hmiLevel.equals(HMILevel.HMI_FULL)) || (hmiLevel.equals(HMILevel.HMI_LIMITED))) {
			if (!driverDistStatus) {
				return LockScreenStatus.OPTIONAL;
			} else {
				return LockScreenStatus.REQUIRED;
			}
		}
		return LockScreenStatus.OFF;
	}

	private void downloadLockScreenIcon(final String url){
		new Thread(new Runnable(){
			@Override
			public void run(){
				try{
					lockScreenOEMIcon = HttpUtils.downloadImage(url);
					Log.i(TAG, "Lock Screen Icon Downloaded");
				}catch(IOException e){
					Log.e(TAG, "Lock Screen Icon Error Downloading");
				}
			}
		}).start();
	}

}

{'fraction_non_alphanumeric': 0.09131659100051721, 'fraction_numerical': 0.000804551462559623, 'mean_word_length': 4.4144368388301185, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4744182', 'n_tokens_mistral': 5957, 'n_tokens_neox': 5164, 'n_words': 1236}