package com.yotadevices.sdk;
import com.yotadevices.sdk.Constants.SystemBSFlags;
import com.yotadevices.sdk.utils.EinkUtils;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.hardware.display.DisplayManager;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* This class is used to draw on back screen
*/
public class BSDrawer extends Drawer {
private static final int DPI = 240;
private static final int BS_SCREEN_WIDTH = 540;
private static final int BS_SCREEN_HEIGHT = 960;
/**
* Back Screen width
*/
public static final int SCREEN_WIDTH = BS_SCREEN_WIDTH;
/**
* Back Screen height
*/
public static final int SCREEN_HEIGHT = BS_SCREEN_HEIGHT;
private static final int TYPE_DISPLAY_EPD = getDisplayTypeEPD();
public static int TYPE_LAYOUT_EPD = getLayoutTypeEpd("TYPE_EPD");
public static int TYPE_LAYOUT_NAVIGATION_BAR = getLayoutTypeEpd("TYPE_NAVIGATION_BAR");
private WeakReference<BSActivity> mActivity;
private Context mContext;
private Context mEpdContext;
private ViewGroup mParentView;
private ViewGroup mBlankView;
private boolean isShowEpdView;
private boolean isShowBlankView;
private LayoutInflater mEpdInflater;
private int mNavigationBarHeight;
private int mLayoutType = TYPE_LAYOUT_EPD;
public BSDrawer(BSActivity activity) {
mActivity = new WeakReference<BSActivity>(activity);
mContext = activity.getContext();
final Resources res = mContext.getResources();
mNavigationBarHeight = res.getDimensionPixelSize(R.dimen.navigation_panel_height);
initDisplay();
}
public BSDrawer(BSActivity activity, int layoutType) {
this(activity);
mLayoutType = layoutType;
}
public void setLayoutType(int layoutType) {
mLayoutType = layoutType;
}
private void initDisplay() {
Display display = getEpdDisplay(mContext);
if (display != null)
initEpdDisplay(display);
}
private static Display getEpdDisplay(Context context) {
DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
for (Display d : dm.getDisplays()) {
if (getTypeDisplay(d) == TYPE_DISPLAY_EPD) {
return d;
}
}
return null;
}
private static int getTypeDisplay(Display d) {
try {
Method m = android.view.Display.class.getDeclaredMethod("getType");
return (Integer) m.invoke(d, new Object[] {});
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
private static int getDisplayTypeEPD() {
try {
Field field = android.view.Display.class.getDeclaredField("TYPE_EPD");
return (Integer) field.get(null);
} catch (Exception unused) {
return 6;// magic type EPD
}
}
private static int getLayoutTypeEpd(String type) {
try {
Field field = android.view.WindowManager.LayoutParams.class.getDeclaredField(type);
return (Integer) field.get(null);
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
public static Context createEpdContext(Context context) {
return context.createDisplayContext(getEpdDisplay(context));
}
private void initEpdDisplay(Display d) {
mEpdContext = mContext.createDisplayContext(d);
mEpdInflater = (LayoutInflater) mEpdContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mParentView = createParentEpdView(mEpdContext);
mBlankView = createParentEpdView(mEpdContext);
}
public void showBlankView() {
if (!isShowBSParentView()) {
getWindowManager().addView(mBlankView, getDefaultLayoutParams());
isShowBlankView = true;
}
}
private void hideBlankView() {
getWindowManager().removeView(mBlankView);
isShowBlankView = false;
}
private WindowManager getWindowManager() {
return mEpdContext != null ? (WindowManager) mEpdContext.getSystemService(Context.WINDOW_SERVICE) : null;
}
private LayoutParams getDefaultLayoutParams() {
return new LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, mLayoutType,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, -1);
}
private LayoutParams applySystemIUVisibility(LayoutParams lp, int visibility) {
if (lp != null) {
boolean hideNavigation = (visibility & SystemBSFlags.SYSTEM_BS_UI_FLAG_HIDE_NAVIGATION) != 0;
boolean translucentNavigation = (visibility & SystemBSFlags.SYSTEM_BS_UI_FLAG_TRANSLUCENT_NAVIGATION) != 0;
int y = 0;
int height = BS_SCREEN_HEIGHT - y - ((hideNavigation || translucentNavigation) ? 0 : mNavigationBarHeight);
lp.y = y;
lp.height = height;
lp.gravity = Gravity.TOP;
}
return lp;
}
private ViewGroup createParentEpdView(Context epdContext) {
ViewGroup group = new FrameLayout(epdContext);
group.setBackgroundColor(Color.BLACK);
return group;
}
/**
* @hide
*/
private synchronized boolean isShowBSParentView() {
return isShowEpdView;
}
/**
* @hide only for inner usage
* @param initialWaveform
* @param initialDithering
*/
@Override
public synchronized void addBSParentView(Waveform initialWaveform, Dithering initialDithering) {
if (!isShowBSParentView()) {
WindowManager wm = getWindowManager();
LayoutParams lp = getDefaultLayoutParams();
BSActivity activity = mActivity.get();
if (activity != null) {
activity.onPrepareLayoutParams(lp);
applySystemIUVisibility(lp, activity.getSytemBSUiVisibility());
}
EinkUtils.setViewDithering(mParentView, initialDithering);
EinkUtils.setViewWaveform(mParentView, initialWaveform);
wm.addView(mParentView, lp);
//EinkUtils.setViewDithering(mParentView, Dithering.DITHER_DEFAULT);
//EinkUtils.setViewWaveform(mParentView, Waveform.WAVEFORM_DEFAULT);
// When BS layout is added we perform FULL update to remove all
// ghosting
// from previous BSActivity
//EinkUtils.performSingleUpdate(mParentView, initialWaveform, initialDithering, 0);
isShowEpdView = true;
if (isShowBlankView) {
hideBlankView();
}
}
}
/**
* @hide only for inner usage
*/
@Override
public synchronized void removeBSParentView() {
if (isShowBSParentView()) {
WindowManager wm = (WindowManager) mEpdContext.getSystemService(Context.WINDOW_SERVICE);
wm.removeView(mParentView);
isShowEpdView = false;
}
}
private Context getContext() {
return mContext;
}
/**
* Adds a child view with the specified layout parameters.
*
* @param child
* the child view to add
* @param params
* the layout parameters to set on the child
*/
@Override
public void addViewToBS(View child, ViewGroup.LayoutParams params) {
mParentView.addView(child, params);
}
/**
* <p>
* Adds a child view. If no layout parameters are already set on the child,
* the default parameters for this ViewGroup are set on the child.
* </p>
*
* @param child
* the child view to add
*/
public void addViewToBS(View child) {
mParentView.addView(child);
}
/**
* Look for a child view with the given id. If this view has the given id,
* return this view.
*
* @param id
* The id to search for.
* @return The view that has the given id in the hierarchy or null
*/
public View findViewById(int id) {
return mParentView != null ? mParentView.findViewById(id) : null;
}
/**
* @return Back screen context for creating a view.
*/
@Override
public Context getBSContext() {
return mEpdContext;
}
/**
* Quick access to the {@link LayoutInflater} instance that this Window
* retrieved from its back screen Context.
*
* @return LayoutInflater The LayoutInflater for the back screen.
*/
@Override
public LayoutInflater getBSLayoutInflater() {
return mEpdInflater;
}
/**
* Removes a view from the back screen.
*
* @param view
* the view to remove from back screen
*/
@Override
public void removeViewFromBS(View view) {
if (isShowBSParentView()) {
mParentView.removeView(view);
}
}
@Override
public void updateViewLayout(int visibility) {
if (isShowBSParentView()) {
WindowManager wm = getWindowManager();
LayoutParams lp = getDefaultLayoutParams();
applySystemIUVisibility(lp, visibility);
wm.updateViewLayout(mParentView, lp);
}
}
public ViewGroup getParentView() {
return mParentView;
}
}