From ef9a54ab790d882504c17b61eec836cf03b6d422 Mon Sep 17 00:00:00 2001 From: Konstantin Pastbin Date: Sun, 12 Jun 2022 13:35:28 +0300 Subject: [PATCH] [android] Remove ViewServer Signed-off-by: Konstantin Pastbin --- .../maps/base/BaseActivityDelegate.java | 4 - .../src/com/mapswithme/util/ViewServer.java | 844 ------------------ 2 files changed, 848 deletions(-) delete mode 100644 android/src/com/mapswithme/util/ViewServer.java diff --git a/android/src/com/mapswithme/maps/base/BaseActivityDelegate.java b/android/src/com/mapswithme/maps/base/BaseActivityDelegate.java index 2dcb963567..e14336b6dd 100644 --- a/android/src/com/mapswithme/maps/base/BaseActivityDelegate.java +++ b/android/src/com/mapswithme/maps/base/BaseActivityDelegate.java @@ -10,7 +10,6 @@ import androidx.annotation.Nullable; import com.mapswithme.util.Config; import com.mapswithme.util.CrashlyticsUtils; import com.mapswithme.util.Utils; -import com.mapswithme.util.ViewServer; import com.mapswithme.util.concurrency.UiThread; import com.mapswithme.util.log.Logger; import com.mapswithme.util.log.LoggerFactory; @@ -55,13 +54,11 @@ public class BaseActivityDelegate public void onDestroy() { logLifecycleMethod("onDestroy()"); - ViewServer.get(mActivity.get()).removeWindow(mActivity.get()); } public void onPostCreate() { logLifecycleMethod("onPostCreate()"); - ViewServer.get(mActivity.get()).addWindow(mActivity.get()); } public void onStart() @@ -77,7 +74,6 @@ public class BaseActivityDelegate public void onResume() { logLifecycleMethod("onResume()"); - ViewServer.get(mActivity.get()).setFocusedWindow(mActivity.get()); Utils.showOnLockScreen(Config.isShowOnLockScreenEnabled(), mActivity.get()); } diff --git a/android/src/com/mapswithme/util/ViewServer.java b/android/src/com/mapswithme/util/ViewServer.java deleted file mode 100644 index eeb266a588..0000000000 --- a/android/src/com/mapswithme/util/ViewServer.java +++ /dev/null @@ -1,844 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.mapswithme.util; - -import android.app.Activity; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.os.Build; -import android.text.TextUtils; -import android.util.Log; -import android.view.View; -import android.view.ViewDebug; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.HashMap; -import java.util.List; -import java.util.Map.Entry; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - *

This class can be used to enable the use of HierarchyViewer inside an - * application. HierarchyViewer is an Android SDK tool that can be used - * to inspect and debug the user interface of running applications. For - * security reasons, HierarchyViewer does not work on production builds - * (for instance phones bought in store.) By using this class, you can - * make HierarchyViewer work on any device. You must be very careful - * however to only enable HierarchyViewer when debugging your - * application.

- * - *

To use this view server, your application must require the INTERNET - * permission.

- * - *

The recommended way to use this API is to register activities when - * they are created, and to unregister them when they get destroyed:

- * - *
- * public class MyActivity extends Activity {
- *     public void onCreate(Bundle savedInstanceState) {
- *         super.onCreate(savedInstanceState);
- *         // Set content view, etc.
- *         ViewServer.get(this).addWindow(this);
- *     }
- *       
- *     public void onDestroy() {
- *         super.onDestroy();
- *         ViewServer.get(this).removeWindow(this);
- *     }
- *   
- *     public void onResume() {
- *         super.onResume();
- *         ViewServer.get(this).setFocusedWindow(this);
- *     }
- * }
- * 
- * - *

- * In a similar fashion, you can use this API with an InputMethodService: - *

- * - *
- * public class MyInputMethodService extends InputMethodService {
- *     public void onCreate() {
- *         super.onCreate();
- *         View decorView = getWindow().getWindow().getDecorView();
- *         String name = "MyInputMethodService";
- *         ViewServer.get(this).addWindow(decorView, name);
- *     }
- *
- *     public void onDestroy() {
- *         super.onDestroy();
- *         View decorView = getWindow().getWindow().getDecorView();
- *         ViewServer.get(this).removeWindow(decorView);
- *     }
- *
- *     public void onStartInput(EditorInfo attribute, boolean restarting) {
- *         super.onStartInput(attribute, restarting);
- *         View decorView = getWindow().getWindow().getDecorView();
- *         ViewServer.get(this).setFocusedWindow(decorView);
- *     }
- * }
- * 
- */ -public class ViewServer implements Runnable { - /** - * The default port used to start view servers. - */ - private static final int VIEW_SERVER_DEFAULT_PORT = 4939; - private static final int VIEW_SERVER_MAX_CONNECTIONS = 10; - private static final String BUILD_TYPE_USER = "user"; - - // Debug facility - private static final String LOG_TAG = "ViewServer"; - - private static final String VALUE_PROTOCOL_VERSION = "4"; - private static final String VALUE_SERVER_VERSION = "4"; - - // Protocol commands - // Returns the protocol version - private static final String COMMAND_PROTOCOL_VERSION = "PROTOCOL"; - // Returns the server version - private static final String COMMAND_SERVER_VERSION = "SERVER"; - // Lists all of the available windows in the system - private static final String COMMAND_WINDOW_MANAGER_LIST = "LIST"; - // Keeps a connection open and notifies when the list of windows changes - private static final String COMMAND_WINDOW_MANAGER_AUTOLIST = "AUTOLIST"; - // Returns the focused window - private static final String COMMAND_WINDOW_MANAGER_GET_FOCUS = "GET_FOCUS"; - - private ServerSocket mServer; - private final int mPort; - - private Thread mThread; - private ExecutorService mThreadPool; - - private final List mListeners = - new CopyOnWriteArrayList(); - - private final HashMap mWindows = new HashMap(); - private final ReentrantReadWriteLock mWindowsLock = new ReentrantReadWriteLock(); - - private View mFocusedWindow; - private final ReentrantReadWriteLock mFocusLock = new ReentrantReadWriteLock(); - - private static ViewServer sServer; - - /** - * Returns a unique instance of the ViewServer. This method should only be - * called from the main thread of your application. The server will have - * the same lifetime as your process. - * - * If your application does not have the android:debuggable - * flag set in its manifest, the server returned by this method will - * be a dummy object that does not do anything. This allows you to use - * the same code in debug and release versions of your application. - * - * @param context A Context used to check whether the application is - * debuggable, this can be the application context - */ - public static ViewServer get(Context context) { - ApplicationInfo info = context.getApplicationInfo(); - if (BUILD_TYPE_USER.equals(Build.TYPE) && - (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { - if (sServer == null) { - sServer = new ViewServer(ViewServer.VIEW_SERVER_DEFAULT_PORT); - } - - if (!sServer.isRunning()) { - try { - sServer.start(); - } catch (IOException e) { - Log.d(LOG_TAG, "Error:", e); - } - } - } else { - sServer = new NoopViewServer(); - } - - return sServer; - } - - private ViewServer() { - mPort = -1; - } - - /** - * Creates a new ViewServer associated with the specified window manager on the - * specified local port. The server is not started by default. - * - * @param port The port for the server to listen to. - * - * @see #start() - */ - private ViewServer(int port) { - mPort = port; - } - - /** - * Starts the server. - * - * @return True if the server was successfully created, or false if it already exists. - * @throws IOException If the server cannot be created. - * - * @see #stop() - * @see #isRunning() - * @see WindowManagerService#startViewServer(int) - */ - public boolean start() throws IOException { - if (mThread != null) { - return false; - } - - mThread = new Thread(this, "Local View Server [port=" + mPort + "]"); - mThreadPool = Executors.newFixedThreadPool(VIEW_SERVER_MAX_CONNECTIONS); - mThread.start(); - - return true; - } - - /** - * Stops the server. - * - * @return True if the server was stopped, false if an error occurred or if the - * server wasn't started. - * - * @see #start() - * @see #isRunning() - * @see WindowManagerService#stopViewServer() - */ - public boolean stop() { - if (mThread != null) { - mThread.interrupt(); - if (mThreadPool != null) { - try { - mThreadPool.shutdownNow(); - } catch (SecurityException e) { - Log.w(LOG_TAG, "Could not stop all view server threads"); - } - } - - mThreadPool = null; - mThread = null; - - try { - mServer.close(); - mServer = null; - return true; - } catch (IOException e) { - Log.w(LOG_TAG, "Could not close the view server"); - } - } - - mWindowsLock.writeLock().lock(); - try { - mWindows.clear(); - } finally { - mWindowsLock.writeLock().unlock(); - } - - mFocusLock.writeLock().lock(); - try { - mFocusedWindow = null; - } finally { - mFocusLock.writeLock().unlock(); - } - - return false; - } - - /** - * Indicates whether the server is currently running. - * - * @return True if the server is running, false otherwise. - * - * @see #start() - * @see #stop() - * @see WindowManagerService#isViewServerRunning() - */ - public boolean isRunning() { - return mThread != null && mThread.isAlive(); - } - - /** - * Invoke this method to register a new view hierarchy. - * - * @param activity The activity whose view hierarchy/window to register - * - * @see #addWindow(View, String) - * @see #removeWindow(Activity) - */ - public void addWindow(Activity activity) { - String name = activity.getTitle().toString(); - if (TextUtils.isEmpty(name)) { - name = activity.getClass().getCanonicalName() + - "/0x" + System.identityHashCode(activity); - } else { - name += "(" + activity.getClass().getCanonicalName() + ")"; - } - addWindow(activity.getWindow().getDecorView(), name); - } - - /** - * Invoke this method to unregister a view hierarchy. - * - * @param activity The activity whose view hierarchy/window to unregister - * - * @see #addWindow(Activity) - * @see #removeWindow(View) - */ - public void removeWindow(Activity activity) { - removeWindow(activity.getWindow().getDecorView()); - } - - /** - * Invoke this method to register a new view hierarchy. - * - * @param view A view that belongs to the view hierarchy/window to register - * @name name The name of the view hierarchy/window to register - * - * @see #removeWindow(View) - */ - public void addWindow(View view, String name) { - mWindowsLock.writeLock().lock(); - try { - mWindows.put(view.getRootView(), name); - } finally { - mWindowsLock.writeLock().unlock(); - } - fireWindowsChangedEvent(); - } - - /** - * Invoke this method to unregister a view hierarchy. - * - * @param view A view that belongs to the view hierarchy/window to unregister - * - * @see #addWindow(View, String) - */ - public void removeWindow(View view) { - mWindowsLock.writeLock().lock(); - try { - mWindows.remove(view.getRootView()); - } finally { - mWindowsLock.writeLock().unlock(); - } - fireWindowsChangedEvent(); - } - - /** - * Invoke this method to change the currently focused window. - * - * @param activity The activity whose view hierarchy/window hasfocus, - * or null to remove focus - */ - public void setFocusedWindow(Activity activity) { - setFocusedWindow(activity.getWindow().getDecorView()); - } - - /** - * Invoke this method to change the currently focused window. - * - * @param view A view that belongs to the view hierarchy/window that has focus, - * or null to remove focus - */ - public void setFocusedWindow(View view) { - mFocusLock.writeLock().lock(); - try { - mFocusedWindow = view == null ? null : view.getRootView(); - } finally { - mFocusLock.writeLock().unlock(); - } - fireFocusChangedEvent(); - } - - /** - * Main server loop. - */ - public void run() { - try { - mServer = new ServerSocket(mPort, VIEW_SERVER_MAX_CONNECTIONS, InetAddress.getLocalHost()); - } catch (Exception e) { - Log.w(LOG_TAG, "Starting ServerSocket error: ", e); - } - - while (mServer != null && Thread.currentThread() == mThread) { - // Any uncaught exception will crash the system process - try { - Socket client = mServer.accept(); - if (mThreadPool != null) { - mThreadPool.execute(new ViewServerWorker(client)); - } else { - try { - client.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } catch (Exception e) { - Log.w(LOG_TAG, "Connection error: ", e); - } - } - } - - private static boolean writeValue(Socket client, String value) { - boolean result; - BufferedWriter out = null; - try { - OutputStream clientStream = client.getOutputStream(); - out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); - out.write(value); - out.write("\n"); - out.flush(); - result = true; - } catch (Exception e) { - result = false; - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) { - result = false; - } - } - } - return result; - } - - private void fireWindowsChangedEvent() { - for (WindowListener listener : mListeners) { - listener.windowsChanged(); - } - } - - private void fireFocusChangedEvent() { - for (WindowListener listener : mListeners) { - listener.focusChanged(); - } - } - - private void addWindowListener(WindowListener listener) { - if (!mListeners.contains(listener)) { - mListeners.add(listener); - } - } - - private void removeWindowListener(WindowListener listener) { - mListeners.remove(listener); - } - - private interface WindowListener { - void windowsChanged(); - void focusChanged(); - } - - private static class UncloseableOutputStream extends OutputStream { - private final OutputStream mStream; - - UncloseableOutputStream(OutputStream stream) { - mStream = stream; - } - - public void close() throws IOException { - // Don't close the stream - } - - public boolean equals(Object o) { - return mStream.equals(o); - } - - public void flush() throws IOException { - mStream.flush(); - } - - public int hashCode() { - return mStream.hashCode(); - } - - public String toString() { - return mStream.toString(); - } - - public void write(byte[] buffer, int offset, int count) - throws IOException { - mStream.write(buffer, offset, count); - } - - public void write(byte[] buffer) throws IOException { - mStream.write(buffer); - } - - public void write(int oneByte) throws IOException { - mStream.write(oneByte); - } - } - - private static class NoopViewServer extends ViewServer { - private NoopViewServer() { - } - - @Override - public boolean start() throws IOException { - return false; - } - - @Override - public boolean stop() { - return false; - } - - @Override - public boolean isRunning() { - return false; - } - - @Override - public void addWindow(Activity activity) { - } - - @Override - public void removeWindow(Activity activity) { - } - - @Override - public void addWindow(View view, String name) { - } - - @Override - public void removeWindow(View view) { - } - - @Override - public void setFocusedWindow(Activity activity) { - } - - @Override - public void setFocusedWindow(View view) { - } - - @Override - public void run() { - } - } - - private class ViewServerWorker implements Runnable, WindowListener { - private final Socket mClient; - private boolean mNeedWindowListUpdate; - private boolean mNeedFocusedWindowUpdate; - - private final Object[] mLock = new Object[0]; - - public ViewServerWorker(Socket client) { - mClient = client; - mNeedWindowListUpdate = false; - mNeedFocusedWindowUpdate = false; - } - - public void run() { - BufferedReader in = null; - try { - in = new BufferedReader(new InputStreamReader(mClient.getInputStream()), 1024); - - final String request = in.readLine(); - - String command; - String parameters; - - int index = request.indexOf(' '); - if (index == -1) { - command = request; - parameters = ""; - } else { - command = request.substring(0, index); - parameters = request.substring(index + 1); - } - - boolean result; - if (COMMAND_PROTOCOL_VERSION.equalsIgnoreCase(command)) { - result = writeValue(mClient, VALUE_PROTOCOL_VERSION); - } else if (COMMAND_SERVER_VERSION.equalsIgnoreCase(command)) { - result = writeValue(mClient, VALUE_SERVER_VERSION); - } else if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) { - result = listWindows(mClient); - } else if (COMMAND_WINDOW_MANAGER_GET_FOCUS.equalsIgnoreCase(command)) { - result = getFocusedWindow(mClient); - } else if (COMMAND_WINDOW_MANAGER_AUTOLIST.equalsIgnoreCase(command)) { - result = windowManagerAutolistLoop(); - } else { - result = windowCommand(mClient, command, parameters); - } - - if (!result) { - Log.w(LOG_TAG, "An error occurred with the command: " + command); - } - } catch(IOException e) { - Log.w(LOG_TAG, "Connection error: ", e); - } finally { - if (in != null) { - try { - in.close(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - if (mClient != null) { - try { - mClient.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - private boolean windowCommand(Socket client, String command, String parameters) { - boolean success = true; - BufferedWriter out = null; - - try { - // Find the hash code of the window - int index = parameters.indexOf(' '); - if (index == -1) { - index = parameters.length(); - } - final String code = parameters.substring(0, index); - int hashCode = (int) Long.parseLong(code, 16); - - // Extract the command's parameter after the window description - if (index < parameters.length()) { - parameters = parameters.substring(index + 1); - } else { - parameters = ""; - } - - final View window = findWindow(hashCode); - if (window == null) { - return false; - } - - // call stuff - final Method dispatch = ViewDebug.class.getDeclaredMethod("dispatchCommand", - View.class, String.class, String.class, OutputStream.class); - dispatch.setAccessible(true); - dispatch.invoke(null, window, command, parameters, - new UncloseableOutputStream(client.getOutputStream())); - - if (!client.isOutputShutdown()) { - out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); - out.write("DONE\n"); - out.flush(); - } - - } catch (Exception e) { - Log.w(LOG_TAG, "Could not send command " + command + - " with parameters " + parameters, e); - success = false; - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) { - success = false; - } - } - } - - return success; - } - - private View findWindow(int hashCode) { - if (hashCode == -1) { - View window = null; - mWindowsLock.readLock().lock(); - try { - window = mFocusedWindow; - } finally { - mWindowsLock.readLock().unlock(); - } - return window; - } - - - mWindowsLock.readLock().lock(); - try { - for (Entry entry : mWindows.entrySet()) { - if (System.identityHashCode(entry.getKey()) == hashCode) { - return entry.getKey(); - } - } - } finally { - mWindowsLock.readLock().unlock(); - } - - return null; - } - - private boolean listWindows(Socket client) { - boolean result = true; - BufferedWriter out = null; - - try { - mWindowsLock.readLock().lock(); - - OutputStream clientStream = client.getOutputStream(); - out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); - - for (Entry entry : mWindows.entrySet()) { - out.write(Integer.toHexString(System.identityHashCode(entry.getKey()))); - out.write(' '); - out.append(entry.getValue()); - out.write('\n'); - } - - out.write("DONE.\n"); - out.flush(); - } catch (Exception e) { - result = false; - } finally { - mWindowsLock.readLock().unlock(); - - if (out != null) { - try { - out.close(); - } catch (IOException e) { - result = false; - } - } - } - - return result; - } - - private boolean getFocusedWindow(Socket client) { - boolean result = true; - String focusName = null; - - BufferedWriter out = null; - try { - OutputStream clientStream = client.getOutputStream(); - out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); - - View focusedWindow = null; - - mFocusLock.readLock().lock(); - try { - focusedWindow = mFocusedWindow; - } finally { - mFocusLock.readLock().unlock(); - } - - if (focusedWindow != null) { - mWindowsLock.readLock().lock(); - try { - focusName = mWindows.get(mFocusedWindow); - } finally { - mWindowsLock.readLock().unlock(); - } - - out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); - out.write(' '); - out.append(focusName); - } - out.write('\n'); - out.flush(); - } catch (Exception e) { - result = false; - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) { - result = false; - } - } - } - - return result; - } - - public void windowsChanged() { - synchronized (mLock) { - mNeedWindowListUpdate = true; - mLock.notifyAll(); - } - } - - public void focusChanged() { - synchronized (mLock) { - mNeedFocusedWindowUpdate = true; - mLock.notifyAll(); - } - } - - private boolean windowManagerAutolistLoop() { - addWindowListener(this); - BufferedWriter out = null; - try { - out = new BufferedWriter(new OutputStreamWriter(mClient.getOutputStream())); - while (!Thread.interrupted()) { - boolean needWindowListUpdate = false; - boolean needFocusedWindowUpdate = false; - synchronized (mLock) { - while (!mNeedWindowListUpdate && !mNeedFocusedWindowUpdate) { - mLock.wait(); - } - if (mNeedWindowListUpdate) { - mNeedWindowListUpdate = false; - needWindowListUpdate = true; - } - if (mNeedFocusedWindowUpdate) { - mNeedFocusedWindowUpdate = false; - needFocusedWindowUpdate = true; - } - } - if (needWindowListUpdate) { - out.write("LIST UPDATE\n"); - out.flush(); - } - if (needFocusedWindowUpdate) { - out.write("FOCUS UPDATE\n"); - out.flush(); - } - } - } catch (Exception e) { - Log.w(LOG_TAG, "Connection error: ", e); - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) { - // Ignore - } - } - removeWindowListener(this); - } - return true; - } - } -}