[Android] Proceso de relación del código fuente de WMS de la ventana de actividad

1. Relación del diagrama de clases

system_server_AMS class diagram_1:
Inserte la descripción de la imagen aquí
Activity_Window_ diagrama de clases relacionado:
Inserte la descripción de la imagen aquí
system_server_AMS class diagram_2:
Inserte la descripción de la imagen aquí
diagrama de clases general:
Inserte la descripción de la imagen aquí

diagrama de flujo:
Inserte la descripción de la imagen aquí

2. Conceptos relacionados

1. ActivityThread: es la clase de subproceso principal de la aplicación. Todos los programas APK tienen y solo un ActivityThread. La entrada del programa es la función estática main () de esta clase.
Activity: Activity contiene una ventana, que se encuentra en el método adjunto de Activity Cree una ventana llamando a new PhoneWindow ();
2. PhoneWindow: hereda la clase Window, envuelve un FrameLayout hasta cierto punto y proporciona un conjunto de interfaces de operación de ventana generales, incluido un DecorView
3. Vista: la interfaz de usuario más básica Componente, que representa un área rectangular en la pantalla,
4. DecorView: esta clase es una subclase de FrameLayout y es una clase interna en PhoneWindow. Decoración en inglés es Decoración, que significa "decoración". DecorView es modificar el FrameLayout ordinario, como agregar una barra de título general y responder a mensajes clave específicos. ;
5. Ventana: Representa la ventana de nivel superior, la visualización de la interfaz de administración y la respuesta a los eventos; cada Actividad creará un objeto PhoneWindow, que es la interfaz entre la Actividad y todo el sistema View. Esta clase proporciona un conjunto de ventanas comunes (Ventana) API operativa, la ventana aquí está solo en el nivel del programa. La ventana administrada por WMS no es una clase Window, sino una clase View o ViewGroup, que generalmente se refiere a la clase DecorView, es decir, DecorView es una ventana administrada por WmS. La ventana es de tipo abstracto.
6, WindowManager: una interfaz heredada de ViewManager. El administrador de ventanas del proceso de aplicación; hay una implementación WindowManagerImpl; se
usa principalmente para administrar algunos estados, atributos, adición de vistas, eliminación, actualización, orden de ventanas, recopilación de mensajes y procesamiento de la ventana.
7. ViewRootImpl: interactúa con el administrador de ventanas global a través de la interfaz IWindowSession: control de interfaz y respuesta de mensajes; cuando WMS administra la ventana del cliente, el cliente debe ser notificado para realizar ciertas operaciones, que se realizan a través de mensajes asincrónicos

Tres pasos

Paso 1:
Cuando se inicia la Actividad, el proceso system_server pasa el scheduleLaunchActivit () del agente remoto AMS (ActivityManagerService) ApplicationThreadProxy (es decir, el Binder del proceso de aplicación, IApplicationThread), marcando SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, y el controlador del binder subyacente inicia el proceso de aplicación dentro del proceso de Actividad de la aplicación. El onTransact de la clase padre ApplicationNative de la clase ApplicationThread, y luego a scheduleLaunchActivity ().
Paso 2:
La scheduleLaunchActivity de ApplicationThread: a través de sendMessage (H.LAUNCH_ACTIVITY, r), el procesamiento H del ActivityThread enviado al subproceso UI es handleLaunchActivity:
ActivityThread.java:

public final class ActivityThread {
    
    
      private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    
    
        // Initialize before creating the activity
        WindowManagerGlobal.initialize();
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
    
    
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        ...
        } 
    }
}

Entre ellos, WindowManagerGlobal.initialize; es el agente remoto IWindowManager que primero obtiene WMS (WindowManagerService)

WindowManagerGlobal.java :

public final class WindowManagerGlobal {
    
    
    public static void initialize() {
    
    
        getWindowManagerService();
    }
    public static IWindowManager getWindowManagerService() {
    
    
        synchronized (WindowManagerGlobal.class) {
    
    
            if (sWindowManagerService == null) {
    
    
                sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
                try {
    
    
                    sWindowManagerService = getWindowManagerService();
                    ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
                } catch (RemoteException e) {
    
    
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowManagerService;
        }
    }
}

Actividad a = performLaunchActivity (r, customIntent); Use ClassLoader para cargar XXXActivity, que creará ContextImpl, si la aplicación no se ha iniciado, primero creará Applicaition y onCreate, y luego llamará a XXXActivity attach ();
En adjunto: creará Cambie la ventana correspondiente de la actividad, que es PhoneWindow, y la asociación entre phoneWindow y WindowManagerImpl:
Activity:

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window) {
    
    
        attachBaseContext(context);
        mFragments.attachHost(null /*parent*/);
        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        mMainThread = aThread;
        mInstrumentation = instr;
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
    
    
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
}

Entre ellos: (WindowManager) context.getSystemService (Context.WINDOW_SERVICE) obtiene WindowManagerImpl:
aquí irá a ContextImpl.getSystemService:

class ContextImpl extends Context {
    
       
  @Override
    public Object getSystemService(String name) {
    
    
        return SystemServiceRegistry.getSystemService(this, name);
    }
}

SystemServiceRegistry:

final class SystemServiceRegistry {
    
    
  public static Object getSystemService(ContextImpl ctx, String name) {
    
    
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }
  private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();
    private static int sServiceCacheSize;
    static {
    
    
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
    
    
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
    
    
                return AccessibilityManager.getInstance(ctx);
            }});
    registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
    
    
            @Override
            public WindowManager createService(ContextImpl ctx) {
    
    
                return new WindowManagerImpl(ctx);
            }});
}

El resultado es nuevo WindowManagerImpl (ctx); En la función performLaunchActivity, después de adjuntar, continúe llamando a mInstrumentation.callActivityOnCreate para implementar el onCreate de XXXActivity. En este momento, todos escribirán setContentView (R.layout.xxx) Paso
3:
Activity.setContentView ():
Llamará a getWindow (). SetContentView (layoutResID), que es setContentView en la clase PhoneWindow: principalmente crea DecorView mDecor (Esta es la vista de nivel superior de la ventana, que contiene la decoración de la ventana) en PhoneWindow, y luego busca android desde mDecor. R.id.content: mContentParent (ViewGroup), luego agregue la Vista establecida por la actividad a mContentParent.addView (view, params);

public void setContentView(@LayoutRes int layoutResID) {
    
    
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
}

PhoneWindow:

public class PhoneWindow extends Window implements MenuBuilder.Callback {
    
    
  public void setContentView(int layoutResID) {
    
    
        
        if (mContentParent == null) {
    
    
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
    
    
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
    
    
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
    
    
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
    
    
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }
}

Paso 4:
Después de que la función ActivitThread.handleLaunchActivity complete performLaunchActivity, vaya a la función handleResumeActivity y muestre start r = performResumeActivity (token, clearHide, motivo); para continuar conResume of XXXActivity.
Luego, se establecerá el tipo de ventana para la ventana correspondiente de la Actividad: ** l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION, ** WMS debe operar en la ventana, cada actividad corresponde a una ventana, Framework definirá varios tipos de ventana, como Ventana del sistema, ventana de la aplicación, ventana secundaria, etc. El tipo aquí es muy importante, sin esto, la ventana no puede mostrarlo.
Luego llamará a ViewManager wm = a.getWindowManager (); wm.addView (decor, l); a WindowManagerImpl.addView:
ActivityThread:

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    
    
        ActivityClientRecord r = mActivities.get(token);
        ...
        r = performResumeActivity(token, clearHide, reason);
        ...
            if (r.window == null && !a.mFinished && willBeVisible) {
    
    
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (r.mPreserveWindow) {
    
    
                    a.mWindowAdded = true;
                    r.mPreserveWindow = false;
                   
                    ViewRootImpl impl = decor.getViewRootImpl();
                    if (impl != null) {
    
    
                        impl.notifyChildRebuilt();
                    }
                }
                if (a.mVisibleFromClient && !a.mWindowAdded) {
    
    
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
             ...
    }

Paso 5:
El addView de WindowManagerImpl se llama al addView de WindowManagerGlobal.getInstance ():
esta función creará root = new ViewRootImpl (view.getContext (), display); y luego guardará en mRoots.add (root) y
luego llamará a root.setView ( ver, wparams, panelParentView);

public final class WindowManagerImpl implements WindowManager {
    
    
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    
    
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }
}

public final class WindowManagerGlobal {
    
    
    public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
    
    
        ...
        ViewRootImpl root;
        View panelParentView = null;
        synchronized (mLock) {
    
    
            ...
            root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
        }
        // do this last because it fires off messages to start doing things
        try {
    
    
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
    
    
           
        }
    }
}

Paso 6:
ViewRootImpl.setView (): En
esta función, los objetos IWindowSession mWindowSession y WMS Seesion remoto se obtienen a través de WindowManagerGloabl, y mWindowSession.addToDisplay se realiza en la sesión del proceso system_server.

public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
    
    
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    
    
        synchronized (this) {
    
    
                ....
                try {
    
    
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                }            
            }
        ...
    }
}

Esta mWindowSession es

public static IWindowSession getWindowSession() {
    
    
        synchronized (WindowManagerGlobal.class) {
    
    
            if (sWindowSession == null) {
    
    
                try {
    
    
                    InputMethodManager imm = InputMethodManager.getInstance();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
    
    
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
    
    
                                    ValueAnimator.setDurationScale(scale);
                                }
                            },
                            imm.getClient(), imm.getInputContext());
                } catch (RemoteException e) {
    
    
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }

Llame al método openSession de WindowManagerService:

public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    
    
   @Override
    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext) {
    
    
        if (client == null) throw new IllegalArgumentException("null client");
        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
        Session session = new Session(this, callback, client, inputContext);
        return session;
    }
}

Supongo que te gusta

Origin blog.csdn.net/sinat_36955332/article/details/108488674
Recomendado
Clasificación