package org.emdev.ui.uimanager;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.emdev.BaseDroidApp;
@TargetApi(11)
public class UIManager3x implements IUIManager {
private static final String SYS_UI_CLS = "com.android.systemui.SystemUIService";
private static final String SYS_UI_PKG = "com.android.systemui";
private static final ComponentName SYS_UI = new ComponentName(SYS_UI_PKG, SYS_UI_CLS);
private static final String SU_PATH1 = "/system/bin/su";
private static final String SU_PATH2 = "/system/xbin/su";
private static final String AM_PATH = "/system/bin/am";
private static final Map<ComponentName, Data> data = new HashMap<ComponentName, Data>() {
/**
*
*/
private static final long serialVersionUID = -6627308913610357179L;
@Override
public Data get(final Object key) {
Data existing = super.get(key);
if (existing == null) {
existing = new Data();
put((ComponentName) key, existing);
}
return existing;
}
};
@Override
public void setFullScreenMode(final Activity activity, final View view, final boolean fullScreen) {
data.get(activity.getComponentName()).fullScreen = fullScreen;
if (fullScreen) {
stopSystemUI(activity);
} else {
startSystemUI(activity);
}
}
@Override
public void onMenuOpened(final Activity activity) {
if (data.get(activity.getComponentName()).fullScreen
&& data.get(activity.getComponentName()).fullScreenState.get()) {
startSystemUI(activity);
}
}
@Override
public void onMenuClosed(final Activity activity) {
if (data.get(activity.getComponentName()).fullScreen
&& !data.get(activity.getComponentName()).fullScreenState.get()) {
stopSystemUI(activity);
}
}
@Override
public void onPause(final Activity activity) {
if (data.get(activity.getComponentName()).fullScreen
&& data.get(activity.getComponentName()).fullScreenState.get()) {
startSystemUI(activity);
}
}
@Override
public void onResume(final Activity activity) {
if (data.get(activity.getComponentName()).fullScreen
&& !data.get(activity.getComponentName()).fullScreenState.get()) {
stopSystemUI(activity);
}
}
@Override
public void onDestroy(final Activity activity) {
if (data.get(activity.getComponentName()).fullScreen
&& data.get(activity.getComponentName()).fullScreenState.get()) {
startSystemUI(activity);
}
}
@Override
public boolean isTabletUi(final Activity activity) {
return true;
}
protected void startSystemUI(final Activity activity) {
if (isSystemUIRunning()) {
data.get(activity.getComponentName()).fullScreenState.set(false);
return;
}
exec(false, activity, AM_PATH, "startservice", "-n", SYS_UI.flattenToString());
}
protected void stopSystemUI(final Activity activity) {
if (!isSystemUIRunning()) {
data.get(activity.getComponentName()).fullScreenState.set(true);
return;
}
final String su = getSuPath();
if (su == null) {
data.get(activity.getComponentName()).fullScreenState.set(false);
return;
}
exec(true, activity, su, "-c", "service call activity 79 s16 " + SYS_UI_PKG);
}
protected boolean isSystemUIRunning() {
final Context ctx = BaseDroidApp.context;
final ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningServiceInfo> rsiList = am.getRunningServices(1000);
for (final RunningServiceInfo rsi : rsiList) {
LCTX.d("Service: " + rsi.service);
if (SYS_UI.equals(rsi.service)) {
LCTX.e("System UI service found");
return true;
}
}
return false;
}
protected void exec(final boolean expected, final Activity activity, final String... as) {
(new Thread(new Runnable() {
@Override
public void run() {
try {
final boolean result = execImpl(as);
data.get(activity.getComponentName()).fullScreenState.set(result ? expected : !expected);
} catch (final Throwable th) {
LCTX.e("Changing full screen mode failed: " + th.getCause());
data.get(activity.getComponentName()).fullScreenState.set(!expected);
}
}
})).start();
}
private boolean execImpl(final String... as) {
try {
LCTX.d("Execute: " + Arrays.toString(as));
final Process process = Runtime.getRuntime().exec(as);
final InputStreamReader r = new InputStreamReader(process.getInputStream());
final StringWriter w = new StringWriter();
final char ac[] = new char[8192];
int i = 0;
do {
i = r.read(ac);
if (i > 0) {
w.write(ac, 0, i);
}
} while (i != -1);
r.close();
process.waitFor();
final int exitValue = process.exitValue();
final String text = w.toString();
LCTX.d("Result code: " + exitValue);
LCTX.d("Output:\n" + text);
return 0 == exitValue;
} catch (final IOException e) {
throw new IllegalStateException(e);
} catch (final InterruptedException e) {
throw new IllegalStateException(e);
}
}
private static String getSuPath() {
final File su1 = new File(SU_PATH1);
if (su1.exists() && su1.isFile() && su1.canExecute()) {
return SU_PATH1;
}
final File su2 = new File(SU_PATH2);
if (su2.exists() && su2.isFile() && su2.canExecute()) {
return SU_PATH2;
}
return null;
}
private static class Data {
boolean fullScreen = false;
boolean titleVisible = true;
final AtomicBoolean fullScreenState = new AtomicBoolean();
}
}