/* * Copyright (C) 2018 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 android.service.autofill.augmented; import static android.service.autofill.augmented.AugmentedAutofillService.sDebug; import static android.service.autofill.augmented.AugmentedAutofillService.sVerbose; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.graphics.Rect; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy; import android.service.autofill.augmented.PresentationParams.Area; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.autofill.IAutofillWindowPresenter; import com.android.internal.annotations.GuardedBy; import dalvik.system.CloseGuard; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.Objects; /** * Handle to a window used to display the augmented autofill UI. * *
The steps to create an augmented autofill UI are: * *
The window is not destroyed and can be shown again */ private void hide() { if (sDebug) Log.d(TAG, "hide()"); synchronized (mLock) { checkNotDestroyedLocked(); if (mWm == null || mFillView == null) { throw new IllegalStateException("update() not called yet, or already destroyed()"); } if (mProxy != null && mShowing) { try { mProxy.requestHideFillUi(); } catch (RemoteException e) { Log.w(TAG, "Error requesting to hide fill window", e); } } } } private void handleShow(WindowManager.LayoutParams p) { if (sDebug) Log.d(TAG, "handleShow()"); synchronized (mLock) { if (mWm != null && mFillView != null) { try { p.flags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; if (!mShowing) { mWm.addView(mFillView, p); mShowing = true; } else { mWm.updateViewLayout(mFillView, p); } } catch (WindowManager.BadTokenException e) { if (sDebug) Log.d(TAG, "Filed with token " + p.token + " gone."); } catch (IllegalStateException e) { if (sDebug) Log.d(TAG, "Exception showing window."); } } } } private void handleHide() { if (sDebug) Log.d(TAG, "handleHide()"); synchronized (mLock) { if (mWm != null && mFillView != null && mShowing) { try { mWm.removeView(mFillView); mShowing = false; } catch (IllegalStateException e) { if (sDebug) Log.d(TAG, "Exception hiding window."); } } } } /** * Destroys the window. * *
Once destroyed, this window cannot be used anymore
*/
public void destroy() {
if (sDebug) {
Log.d(TAG,
"destroy(): mDestroyed=" + mDestroyed + " mShowing=" + mShowing + " mFillView="
+ mFillView);
}
synchronized (mLock) {
if (mDestroyed) return;
if (mUpdateCalled) {
mFillView.setOnClickListener(null);
hide();
mProxy.logEvent(AutofillProxy.REPORT_EVENT_UI_DESTROYED);
}
mDestroyed = true;
mCloseGuard.close();
}
}
@Override
protected void finalize() throws Throwable {
try {
mCloseGuard.warnIfOpen();
destroy();
} finally {
super.finalize();
}
}
private void checkNotDestroyedLocked() {
if (mDestroyed) {
throw new IllegalStateException("already destroyed()");
}
}
/** @hide */
public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
synchronized (this) {
pw.print(prefix); pw.print("destroyed: "); pw.println(mDestroyed);
pw.print(prefix); pw.print("updateCalled: "); pw.println(mUpdateCalled);
if (mFillView != null) {
pw.print(prefix); pw.print("fill window: ");
pw.println(mShowing ? "shown" : "hidden");
pw.print(prefix); pw.print("fill view: ");
pw.println(mFillView);
pw.print(prefix); pw.print("mBounds: ");
pw.println(mBounds);
pw.print(prefix); pw.print("mWm: ");
pw.println(mWm);
}
}
}
/** @hide */
@Override
public void close() {
destroy();
}
private static final class FillWindowPresenter extends IAutofillWindowPresenter.Stub {
private final @NonNull WeakReference