• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
20 import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
21 import static android.view.InsetsSource.ID_IME;
22 import static android.view.WindowInsets.Type.displayCutout;
23 import static android.view.WindowInsets.Type.ime;
24 import static android.view.WindowInsets.Type.mandatorySystemGestures;
25 import static android.view.WindowInsets.Type.systemGestures;
26 
27 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_IME;
28 import static com.android.server.wm.DisplayContentProto.IME_INSETS_SOURCE_PROVIDER;
29 import static com.android.server.wm.DisplayContentProto.INSETS_SOURCE_PROVIDERS;
30 
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.os.Trace;
34 import android.util.ArrayMap;
35 import android.util.ArraySet;
36 import android.util.SparseArray;
37 import android.util.SparseLongArray;
38 import android.util.proto.ProtoOutputStream;
39 import android.view.InsetsSource;
40 import android.view.InsetsSourceControl;
41 import android.view.InsetsState;
42 import android.view.WindowInsets;
43 import android.view.WindowInsets.Type.InsetsType;
44 import android.view.inputmethod.ImeTracker;
45 
46 import com.android.internal.protolog.ProtoLog;
47 import com.android.server.inputmethod.InputMethodManagerInternal;
48 
49 import java.io.PrintWriter;
50 import java.util.ArrayList;
51 import java.util.function.Consumer;
52 
53 /**
54  * Manages global window inset state in the system represented by {@link InsetsState}.
55  */
56 class InsetsStateController {
57 
58     private final InsetsState mLastState = new InsetsState();
59     private final InsetsState mState = new InsetsState();
60     private final DisplayContent mDisplayContent;
61 
62     private final SparseArray<InsetsSourceProvider> mProviders = new SparseArray<>();
63     private final SparseLongArray mSurfaceTransactionIds = new SparseLongArray();
64     private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>>
65             mControlTargetProvidersMap = new ArrayMap<>();
66     private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>>
67             mPendingTargetProvidersMap = new ArrayMap<>();
68     private final SparseArray<InsetsControlTarget> mIdControlTargetMap = new SparseArray<>();
69     private final SparseArray<InsetsControlTarget> mIdFakeControlTargetMap = new SparseArray<>();
70 
71     private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
72         if (w.isReadyToDispatchInsetsState()) {
73             w.notifyInsetsChanged();
74         }
75     };
76     private final InsetsControlTarget mEmptyImeControlTarget = new InsetsControlTarget() {
77         @Override
78         public void notifyInsetsControlChanged(int displayId) {
79             InsetsSourceControl[] controls = getControlsForDispatch(this);
80             if (controls == null) {
81                 return;
82             }
83             for (InsetsSourceControl control : controls) {
84                 if (control.getType() == WindowInsets.Type.ime()) {
85                     mDisplayContent.mWmService.mH.post(() ->
86                             InputMethodManagerInternal.get().removeImeSurface(displayId));
87                 }
88             }
89         }
90     };
91 
92     private @InsetsType int mForcedConsumingTypes;
93 
InsetsStateController(DisplayContent displayContent)94     InsetsStateController(DisplayContent displayContent) {
95         mDisplayContent = displayContent;
96     }
97 
getRawInsetsState()98     InsetsState getRawInsetsState() {
99         return mState;
100     }
101 
getControlsForDispatch(InsetsControlTarget target)102     @Nullable InsetsSourceControl[] getControlsForDispatch(InsetsControlTarget target) {
103         final ArrayList<InsetsSourceProvider> controlled = mControlTargetProvidersMap.get(target);
104         if (controlled == null) {
105             return null;
106         }
107         final int size = controlled.size();
108         final InsetsSourceControl[] result = new InsetsSourceControl[size];
109         for (int i = 0; i < size; i++) {
110             result[i] = controlled.get(i).getControl(target);
111         }
112         return result;
113     }
114 
getSourceProviders()115     SparseArray<InsetsSourceProvider> getSourceProviders() {
116         return mProviders;
117     }
118 
119     /**
120      * @return The provider of a specific source ID.
121      */
getOrCreateSourceProvider(int id, @InsetsType int type)122     InsetsSourceProvider getOrCreateSourceProvider(int id, @InsetsType int type) {
123         InsetsSourceProvider provider = mProviders.get(id);
124         if (provider != null) {
125             return provider;
126         }
127         final InsetsSource source = mState.getOrCreateSource(id, type);
128         provider = id == ID_IME
129                 ? new ImeInsetsSourceProvider(source, this, mDisplayContent)
130                 : new InsetsSourceProvider(source, this, mDisplayContent);
131         provider.setFlags(
132                 (mForcedConsumingTypes & type) != 0
133                         ? FLAG_FORCE_CONSUMING
134                         : 0,
135                 FLAG_FORCE_CONSUMING);
136         mProviders.put(id, provider);
137         return provider;
138     }
139 
getImeSourceProvider()140     ImeInsetsSourceProvider getImeSourceProvider() {
141         return (ImeInsetsSourceProvider) getOrCreateSourceProvider(ID_IME, ime());
142     }
143 
removeSourceProvider(int id)144     void removeSourceProvider(int id) {
145         if (id != ID_IME) {
146             mState.removeSource(id);
147             mProviders.remove(id);
148         }
149     }
150 
setForcedConsumingTypes(@nsetsType int types)151     void setForcedConsumingTypes(@InsetsType int types) {
152         if (mForcedConsumingTypes != types) {
153             mForcedConsumingTypes = types;
154             boolean changed = false;
155             for (int i = mProviders.size() - 1; i >= 0; i--) {
156                 final InsetsSourceProvider provider = mProviders.valueAt(i);
157                 changed |= provider.setFlags(
158                         (types & provider.getSource().getType()) != 0
159                                 ? FLAG_FORCE_CONSUMING
160                                 : 0,
161                         FLAG_FORCE_CONSUMING);
162             }
163             if (changed) {
164                 notifyInsetsChanged();
165             }
166         }
167     }
168 
169     /**
170      * Called when a layout pass has occurred.
171      */
onPostLayout()172     void onPostLayout() {
173         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "ISC.onPostLayout");
174         for (int i = mProviders.size() - 1; i >= 0; i--) {
175             mProviders.valueAt(i).onPostLayout();
176         }
177         if (!mLastState.equals(mState)) {
178             mLastState.set(mState, true /* copySources */);
179             notifyInsetsChanged();
180         }
181         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
182     }
183 
184     /**
185      * Updates {@link WindowState#mAboveInsetsState} for all windows in the display.
186      *
187      * @param notifyInsetsChange {@code true} if the clients should be notified about the change.
188      */
updateAboveInsetsState(boolean notifyInsetsChange)189     void updateAboveInsetsState(boolean notifyInsetsChange) {
190         final InsetsState aboveInsetsState = new InsetsState();
191         aboveInsetsState.set(mState,
192                 displayCutout() | systemGestures() | mandatorySystemGestures());
193         final SparseArray<InsetsSource> localInsetsSourcesFromParent = new SparseArray<>();
194         final ArraySet<WindowState> insetsChangedWindows = new ArraySet<>();
195 
196         // This method will iterate on the entire hierarchy in top to bottom z-order manner. The
197         // aboveInsetsState will be modified as per the insets provided by the WindowState being
198         // visited.
199         mDisplayContent.updateAboveInsetsState(aboveInsetsState, localInsetsSourcesFromParent,
200                 insetsChangedWindows);
201 
202         if (notifyInsetsChange) {
203             for (int i = insetsChangedWindows.size() - 1; i >= 0; i--) {
204                 mDispatchInsetsChanged.accept(insetsChangedWindows.valueAt(i));
205             }
206         }
207     }
208 
onDisplayFramesUpdated(boolean notifyInsetsChange)209     void onDisplayFramesUpdated(boolean notifyInsetsChange) {
210         final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>();
211         mDisplayContent.forAllWindows(w -> {
212             w.mAboveInsetsState.set(mState, displayCutout());
213             insetsChangedWindows.add(w);
214         }, true /* traverseTopToBottom */);
215         if (notifyInsetsChange) {
216             for (int i = insetsChangedWindows.size() - 1; i >= 0; i--) {
217                 mDispatchInsetsChanged.accept(insetsChangedWindows.get(i));
218             }
219         }
220     }
221 
onRequestedVisibleTypesChanged(InsetsTarget caller, @InsetsType int changedTypes, @Nullable ImeTracker.Token statsToken)222     void onRequestedVisibleTypesChanged(InsetsTarget caller, @InsetsType int changedTypes,
223             @Nullable ImeTracker.Token statsToken) {
224         boolean changed = false;
225         for (int i = mProviders.size() - 1; i >= 0; i--) {
226             final InsetsSourceProvider provider = mProviders.valueAt(i);
227             final @InsetsType int type = provider.getSource().getType();
228             final boolean isImeProvider = type == WindowInsets.Type.ime();
229             if ((type & changedTypes) != 0) {
230                 changed |= provider.updateClientVisibility(
231                         caller, isImeProvider ? statsToken : null)
232                         // Fake control target cannot change the client visibility, but it should
233                         // change the insets with its newly requested visibility.
234                         || (caller == provider.getFakeControlTarget());
235             } else if (isImeProvider && android.view.inputmethod.Flags.refactorInsetsController()) {
236                 ImeTracker.forLogging().onCancelled(statsToken,
237                         ImeTracker.PHASE_WM_SET_REMOTE_TARGET_IME_VISIBILITY);
238             }
239         }
240         if (changed) {
241             notifyInsetsChanged();
242             mDisplayContent.updateSystemGestureExclusion();
243 
244             mDisplayContent.getDisplayPolicy().updateSystemBarAttributes();
245         }
246     }
247 
getFakeControllingTypes(InsetsTarget target)248     @InsetsType int getFakeControllingTypes(InsetsTarget target) {
249         @InsetsType int types = 0;
250         for (int i = mProviders.size() - 1; i >= 0; i--) {
251             final InsetsSourceProvider provider = mProviders.valueAt(i);
252             final InsetsControlTarget fakeControlTarget = provider.getFakeControlTarget();
253             if (target == fakeControlTarget) {
254                 types |= provider.getSource().getType();
255             }
256         }
257         return types;
258     }
259 
onImeControlTargetChanged(@ullable InsetsControlTarget imeTarget)260     void onImeControlTargetChanged(@Nullable InsetsControlTarget imeTarget) {
261 
262         // Make sure that we always have a control target for the IME, even if the IME target is
263         // null. Otherwise there is no leash that will hide it and IME becomes "randomly" visible.
264         InsetsControlTarget target = imeTarget != null ? imeTarget : mEmptyImeControlTarget;
265         onControlTargetChanged(getImeSourceProvider(), target, false /* fake */);
266         ProtoLog.d(WM_DEBUG_IME, "onImeControlTargetChanged %s",
267                 target != null && target.getWindow() != null ? target.getWindow() : target);
268         notifyPendingInsetsControlChanged();
269     }
270 
271     /**
272      * Called when the focused window that is able to control the system bars changes.
273      *
274      * @param statusControlling The target that is now able to control the status bar appearance
275      *                          and visibility.
276      * @param navControlling The target that is now able to control the nav bar appearance
277      *                       and visibility.
278      */
onBarControlTargetChanged(@ullable InsetsControlTarget statusControlling, @Nullable InsetsControlTarget fakeStatusControlling, @Nullable InsetsControlTarget navControlling, @Nullable InsetsControlTarget fakeNavControlling)279     void onBarControlTargetChanged(@Nullable InsetsControlTarget statusControlling,
280             @Nullable InsetsControlTarget fakeStatusControlling,
281             @Nullable InsetsControlTarget navControlling,
282             @Nullable InsetsControlTarget fakeNavControlling) {
283         for (int i = mProviders.size() - 1; i >= 0; i--) {
284             final InsetsSourceProvider provider = mProviders.valueAt(i);
285             final @InsetsType int type = provider.getSource().getType();
286             if (type == WindowInsets.Type.statusBars()) {
287                 onControlTargetChanged(provider, statusControlling, false /* fake */);
288                 onControlTargetChanged(provider, fakeStatusControlling, true /* fake */);
289             } else if (type == WindowInsets.Type.navigationBars()) {
290                 onControlTargetChanged(provider, navControlling, false /* fake */);
291                 onControlTargetChanged(provider, fakeNavControlling, true /* fake */);
292             }
293         }
294         notifyPendingInsetsControlChanged();
295     }
296 
notifyControlTargetChanged(@ullable InsetsControlTarget target, InsetsSourceProvider provider)297     void notifyControlTargetChanged(@Nullable InsetsControlTarget target,
298             InsetsSourceProvider provider) {
299         onControlTargetChanged(provider, target, false /* fake */);
300         notifyPendingInsetsControlChanged();
301     }
302 
notifyControlRevoked(@onNull InsetsControlTarget previousControlTarget, InsetsSourceProvider provider)303     void notifyControlRevoked(@NonNull InsetsControlTarget previousControlTarget,
304             InsetsSourceProvider provider) {
305         removeFromControlMaps(previousControlTarget, provider, false /* fake */);
306     }
307 
onControlTargetChanged(InsetsSourceProvider provider, @Nullable InsetsControlTarget target, boolean fake)308     private void onControlTargetChanged(InsetsSourceProvider provider,
309             @Nullable InsetsControlTarget target, boolean fake) {
310         final InsetsControlTarget lastTarget = fake
311                 ? mIdFakeControlTargetMap.get(provider.getSource().getId())
312                 : mIdControlTargetMap.get(provider.getSource().getId());
313         if (target == lastTarget) {
314             return;
315         }
316         if (!provider.isControllable()) {
317             return;
318         }
319         if (fake) {
320             // The fake target updated here will be used to pretend to the app that it's still under
321             // control of the bars while it's not really, but we still need to find out the apps
322             // intentions around showing/hiding. For example, when the transient bars are showing,
323             // and the fake target requests to show system bars, the transient state will be
324             // aborted.
325             provider.updateFakeControlTarget(target);
326         } else {
327             // TODO(b/353463205) if the IME controlTarget changes, any pending requests should fail
328             provider.updateControlForTarget(target, false /* force */,
329                     null /* TODO(b/353463205) check if needed here */);
330 
331             // Get control target again in case the provider didn't accept the one we passed to it.
332             target = provider.getControlTarget();
333             if (target == lastTarget) {
334                 return;
335             }
336         }
337         if (lastTarget != null) {
338             removeFromControlMaps(lastTarget, provider, fake);
339             addToPendingControlMaps(lastTarget, provider);
340         }
341         if (target != null) {
342             addToControlMaps(target, provider, fake);
343             addToPendingControlMaps(target, provider);
344         }
345     }
346 
removeFromControlMaps(@onNull InsetsControlTarget target, InsetsSourceProvider provider, boolean fake)347     private void removeFromControlMaps(@NonNull InsetsControlTarget target,
348             InsetsSourceProvider provider, boolean fake) {
349         final ArrayList<InsetsSourceProvider> array = mControlTargetProvidersMap.get(target);
350         if (array == null) {
351             return;
352         }
353         array.remove(provider);
354         if (array.isEmpty()) {
355             mControlTargetProvidersMap.remove(target);
356         }
357         if (fake) {
358             mIdFakeControlTargetMap.remove(provider.getSource().getId());
359         } else {
360             mIdControlTargetMap.remove(provider.getSource().getId());
361         }
362     }
363 
addToControlMaps(@onNull InsetsControlTarget target, InsetsSourceProvider provider, boolean fake)364     private void addToControlMaps(@NonNull InsetsControlTarget target,
365             InsetsSourceProvider provider, boolean fake) {
366         final ArrayList<InsetsSourceProvider> array = mControlTargetProvidersMap.computeIfAbsent(
367                 target, key -> new ArrayList<>());
368         array.add(provider);
369         if (fake) {
370             mIdFakeControlTargetMap.put(provider.getSource().getId(), target);
371         } else {
372             mIdControlTargetMap.put(provider.getSource().getId(), target);
373         }
374     }
375 
addToPendingControlMaps(@onNull InsetsControlTarget target, InsetsSourceProvider provider)376     private void addToPendingControlMaps(@NonNull InsetsControlTarget target,
377             InsetsSourceProvider provider) {
378         final ArrayList<InsetsSourceProvider> array =
379                 mPendingTargetProvidersMap.computeIfAbsent(target, key -> new ArrayList<>());
380         array.add(provider);
381     }
382 
notifyControlChanged(@onNull InsetsControlTarget target, InsetsSourceProvider provider)383     void notifyControlChanged(@NonNull InsetsControlTarget target, InsetsSourceProvider provider) {
384         addToPendingControlMaps(target, provider);
385         notifyPendingInsetsControlChanged();
386     }
387 
notifySurfaceTransactionReady(InsetsSourceProvider provider, long id, boolean ready)388     void notifySurfaceTransactionReady(InsetsSourceProvider provider, long id, boolean ready) {
389         if (ready) {
390             mSurfaceTransactionIds.put(provider.getSource().getId(), id);
391         } else {
392             mSurfaceTransactionIds.delete(provider.getSource().getId());
393         }
394     }
395 
onAnimatingTypesChanged(InsetsControlTarget target, @Nullable ImeTracker.Token statsToken)396     void onAnimatingTypesChanged(InsetsControlTarget target,
397             @Nullable ImeTracker.Token statsToken) {
398         for (int i = mProviders.size() - 1; i >= 0; i--) {
399             final InsetsSourceProvider provider = mProviders.valueAt(i);
400             final boolean isImeProvider = provider.getSource().getType() == WindowInsets.Type.ime();
401             provider.onAnimatingTypesChanged(target, isImeProvider ? statsToken : null);
402         }
403     }
404 
notifyPendingInsetsControlChanged()405     private void notifyPendingInsetsControlChanged() {
406         if (mPendingTargetProvidersMap.isEmpty()) {
407             return;
408         }
409         final int size = mSurfaceTransactionIds.size();
410         final SparseLongArray surfaceTransactionIds = new SparseLongArray(size);
411         for (int i = 0; i < size; i++) {
412             surfaceTransactionIds.append(
413                     mSurfaceTransactionIds.keyAt(i), mSurfaceTransactionIds.valueAt(i));
414         }
415         mDisplayContent.mWmService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
416             for (int i = 0; i < size; i++) {
417                 final int sourceId = surfaceTransactionIds.keyAt(i);
418                 final InsetsSourceProvider provider = mProviders.get(sourceId);
419                 if (provider == null) {
420                     continue;
421                 }
422                 provider.onSurfaceTransactionCommitted(surfaceTransactionIds.valueAt(i));
423             }
424             final ArraySet<InsetsControlTarget> newControlTargets = new ArraySet<>();
425             int displayId = mDisplayContent.getDisplayId();
426             final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>> pendingControlMap =
427                     mPendingTargetProvidersMap;
428             for (int i = pendingControlMap.size() - 1; i >= 0; i--) {
429                 final InsetsControlTarget target = pendingControlMap.keyAt(i);
430                 final ArrayList<InsetsSourceProvider> providers = pendingControlMap.valueAt(i);
431                 for (int p = providers.size() - 1; p >= 0; p--) {
432                     final InsetsSourceProvider provider = providers.get(p);
433                     if (provider.isLeashInitialized() || provider.getControlTarget() != target) {
434                         // Stop waiting for this provider.
435                         providers.remove(p);
436                     }
437                 }
438                 if (providers.isEmpty()) {
439                     pendingControlMap.removeAt(i);
440 
441                     // All controls of this target are ready to be dispatched.
442                     target.notifyInsetsControlChanged(displayId);
443                     if (mControlTargetProvidersMap.containsKey(target)) {
444                         // We only collect targets who get controls, not lose controls.
445                         newControlTargets.add(target);
446                     }
447                 }
448             }
449 
450             // This updates the insets visibilities AFTER sending current insets state and controls
451             // to the clients, so that the clients can change the current visibilities to the
452             // requested visibilities with animations.
453             for (int i = newControlTargets.size() - 1; i >= 0; i--) {
454                 // TODO(b/353463205) the statsToken shouldn't be null as it is used later in the
455                 //  IME provider. Check if we have to create a new request here
456                 onRequestedVisibleTypesChanged(newControlTargets.valueAt(i),
457                         WindowInsets.Type.all(), null /* statsToken */);
458             }
459             newControlTargets.clear();
460             if (!android.view.inputmethod.Flags.refactorInsetsController()) {
461                 // Check for and try to run the scheduled show IME request (if it exists), as we
462                 // now applied the surface transaction and notified the target of the new control.
463                 getImeSourceProvider().checkAndStartShowImePostLayout();
464             }
465         });
466     }
467 
notifyInsetsChanged()468     void notifyInsetsChanged() {
469         mDisplayContent.notifyInsetsChanged(mDispatchInsetsChanged);
470     }
471 
notifyInsetsChanged(ArraySet<WindowState> changedWindows)472     void notifyInsetsChanged(ArraySet<WindowState> changedWindows) {
473         for (int i = changedWindows.size() - 1; i >= 0; i--) {
474             mDispatchInsetsChanged.accept(changedWindows.valueAt(i));
475         }
476     }
477 
478     /**
479      * Checks if the control target has pending controls.
480      *
481      * @param target the control target to check.
482      */
hasPendingControls(@onNull InsetsControlTarget target)483     boolean hasPendingControls(@NonNull InsetsControlTarget target) {
484         return mPendingTargetProvidersMap.containsKey(target);
485     }
486 
dump(String prefix, PrintWriter pw)487     void dump(String prefix, PrintWriter pw) {
488         pw.println(prefix + "WindowInsetsStateController");
489         prefix = prefix + "  ";
490         mState.dump(prefix, pw);
491         pw.println(prefix + "Control map:");
492         for (int i = mControlTargetProvidersMap.size() - 1; i >= 0; i--) {
493             final InsetsControlTarget controlTarget = mControlTargetProvidersMap.keyAt(i);
494             pw.print(prefix + "  ");
495             pw.print(controlTarget);
496             pw.println(":");
497             final ArrayList<InsetsSourceProvider> providers = mControlTargetProvidersMap.valueAt(i);
498             for (int j = providers.size() - 1; j >= 0; j--) {
499                 final InsetsSourceProvider provider = providers.get(j);
500                 if (provider != null) {
501                     pw.print(prefix + "    ");
502                     if (controlTarget == provider.getFakeControlTarget()) {
503                         pw.print("(fake) ");
504                     }
505                     pw.println(provider.getControl(controlTarget));
506                 }
507             }
508         }
509         if (mControlTargetProvidersMap.isEmpty()) {
510             pw.print(prefix + "  none");
511         }
512         pw.println(prefix + "InsetsSourceProviders:");
513         for (int i = mProviders.size() - 1; i >= 0; i--) {
514             mProviders.valueAt(i).dump(pw, prefix + "  ");
515         }
516         if (mForcedConsumingTypes != 0) {
517             pw.println(prefix + "mForcedConsumingTypes="
518                     + WindowInsets.Type.toString(mForcedConsumingTypes));
519         }
520     }
521 
dumpDebug(ProtoOutputStream proto, @WindowTracingLogLevel int logLevel)522     void dumpDebug(ProtoOutputStream proto, @WindowTracingLogLevel int logLevel) {
523         for (int i = mProviders.size() - 1; i >= 0; i--) {
524             final InsetsSourceProvider provider = mProviders.valueAt(i);
525             provider.dumpDebug(proto,
526                     provider.getSource().getType() == ime()
527                             ? IME_INSETS_SOURCE_PROVIDER
528                             : INSETS_SOURCE_PROVIDERS,
529                     logLevel);
530         }
531     }
532 }
533