[Android] Processo de relacionamento do código-fonte WMS da janela de atividades

1. Relação do diagrama de classes

system_server_AMS class diagram_1:
Insira a descrição da imagem aqui
Activity_Window_ diagrama de classes relacionado:
Insira a descrição da imagem aqui
system_server_AMS class diagram_2:
Insira a descrição da imagem aqui
diagrama geral de classes:
Insira a descrição da imagem aqui

fluxograma:
Insira a descrição da imagem aqui

2. Conceitos relacionados

1. ActivityThread: é a classe de thread principal do aplicativo. Todos os programas APK têm e apenas um ActivityThread. A entrada do programa é a função main () estática desta classe.
Activity: Activity contém uma Window, que está no método attach de Activity Crie uma janela chamando new PhoneWindow ();
2. PhoneWindow: herda a classe Window, envolve um FrameLayout até certo ponto e fornece um conjunto de interfaces de operação de janela geral, incluindo um DecorView
3. View: a IU mais básica Component, que representa uma área retangular na tela;
4. DecorView: esta classe é uma subclasse de FrameLayout e é uma classe interna do PhoneWindow. Decor em inglês é Decoration, que significa "decoração". DecorView é para modificar o FrameLayout comum, como adicionar uma barra de título geral e responder a mensagens chave específicas. ;
5. Janela: representa a janela de nível superior, a exibição da interface de gerenciamento e a resposta aos eventos; cada Activity criará um objeto PhoneWindow, que é a interface entre a Activity e todo o sistema View. Esta classe fornece um conjunto de janelas comuns (Window) API de operação, a janela aqui é apenas no nível do programa.A janela gerenciada pelo WMS não é uma classe Window, mas uma classe View ou ViewGroup, que geralmente se refere à classe DecorView, ou seja, um DecorView é uma janela gerenciada pelo WmS. A janela é um tipo abstrato.
6, WindowManager: uma interface herdada do ViewManager. O gerenciador de janelas do processo do aplicativo; há uma implementação WindowManagerImpl; é
usado principalmente para gerenciar alguns estados, atributos, adição de visualização, exclusão, atualização, ordem das janelas, coleta de mensagens e processamento da janela.
7. ViewRootImpl: interagir com o gerenciador de janela global através da interface IWindowSession: controle da interface e resposta da mensagem; quando o WMS gerencia a janela do cliente, o cliente precisa ser notificado para realizar certas operações, que são feitas por meio de mensagens assíncronas

Três passos

Etapa 1:
Quando a atividade é iniciada, o processo system_server passa pelo scheduleLaunchActivit () do agente remoto AMS (ActivityManagerService) ApplicationThreadProxy (ou seja, o Binder do processo do aplicativo, IApplicationThread), marcando SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, e o binder subjacente do aplicativo ActivityThread para iniciar o processo do aplicativo XXXThread. O onTransact da classe pai ApplicationNative da classe ApplicationThread e, em seguida, para scheduleLaunchActivity (). Etapa
2:
O scheduleLaunchActivity de ApplicationThread: por meio de sendMessage (H.LAUNCH_ACTIVITY, r), o processamento H de ActivityThread enviado para o thread de UI é 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 eles, WindowManagerGlobal.initialize; é o agente remoto IWindowManager que primeiro busca 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;
        }
    }
}

Activity a = performLaunchActivity (r, customIntent); Use ClassLoader para carregar XXXActivity, que criará ContextImpl, se o aplicativo não tiver sido iniciado, primeiro criará Applicaition e onCreate e, em seguida, chamará XXXActivity attach ();
Em attach: criará Altere a janela correspondente da atividade, que é PhoneWindow, e a associação entre phoneWindow e 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 eles: (WindowManager) context.getSystemService (Context.WINDOW_SERVICE) obtém WindowManagerImpl:
aqui irá para 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);
            }});
}

O retorno é novo WindowManagerImpl (ctx); na função performLaunchActivity, depois de anexar, continue chamando mInstrumentation.callActivityOnCreate para implementar onCreate de XXXActivity. Nesse momento, todos escreverão setContentView (R.layout.xxx)
Etapa 3:
Activity.setContentView ():
Irá chamar getWindow (). SetContentView (layoutResID), que é setContentView na classe PhoneWindow: principalmente criar DecorView mDecor (esta é a visualização de nível superior da janela, contendo a decoração da janela) em PhoneWindow e, em seguida, localizar android em mDecor. R.id.content: mContentParent (ViewGroup), em seguida, adicione a Visualização definida pela atividade a mContentParent.addView (visualização, parâmetros);

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;
    }
}


Etapa 4: Depois que a função ActivitThread.handleLaunchActivity conclui performLaunchActivity, vá para a função handleResumeActivity e exiba iniciar r = performResumeActivity (token, clearHide, motivo); para ir emResume de XXXActivity.
Em seguida, o tipo de janela será definido para a janela correspondente da Activity: ** l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION, ** WMS é para operar na janela, cada atividade corresponde a uma janela, o Framework irá definir vários tipos de janela, como Janela do sistema, janela do aplicativo, janela filho, etc. O tipo aqui é muito importante. Sem isso, a janela não pode exibi-lo.
Em seguida, ele chamará para ViewManager wm = a.getWindowManager (); wm.addView (decor, l); para 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);
                }
             ...
    }

Passo 5:
O addView de WindowManagerImpl é chamado para addView de WindowManagerGlobal.getInstance ():
Esta função criará root = new ViewRootImpl (view.getContext (), display); e então salvará em mRoots.add (root) e
então chamará root.setView ( view, 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) {
    
    
           
        }
    }
}

Passo 6:
ViewRootImpl.setView ():
Nesta função, os objetos IWindowSession mWindowSession e WMS Seesion remoto são obtidos por meio de WindowManagerGloabl, e mWindowSession.addToDisplay é executado para a Sessão do processo 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);
                }            
            }
        ...
    }
}

Este mWindowSession é

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;
        }
    }

Chame o 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;
    }
}

Acho que você gosta

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