NotificationInflater.java revision 0f66a4cc16ec1a927c90ac559c73c80ddcb5ee71
11a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek/*
21a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * Copyright (C) 2017 The Android Open Source Project
31a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek *
41a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * Licensed under the Apache License, Version 2.0 (the "License");
51a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * you may not use this file except in compliance with the License.
61a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * You may obtain a copy of the License at
71a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek *
81a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek *      http://www.apache.org/licenses/LICENSE-2.0
91a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek *
101a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * Unless required by applicable law or agreed to in writing, software
111a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * distributed under the License is distributed on an "AS IS" BASIS,
121a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * See the License for the specific language governing permissions and
141a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * limitations under the License
151a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek */
161a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
171a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekpackage com.android.systemui.statusbar.notification;
181a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
1901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinekimport android.annotation.Nullable;
201a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport android.app.Notification;
211a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport android.content.Context;
222630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport android.os.AsyncTask;
2301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinekimport android.os.CancellationSignal;
241a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport android.service.notification.StatusBarNotification;
251a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport android.util.Log;
261a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport android.view.View;
271a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport android.widget.RemoteViews;
281a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
2910790672a98debafb8882971e94ff26aec9a6bfaSelim Cinekimport com.android.internal.annotations.VisibleForTesting;
300f66a4cc16ec1a927c90ac559c73c80ddcb5ee71Selim Cinekimport com.android.systemui.statusbar.Abortable;
311a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport com.android.systemui.statusbar.ExpandableNotificationRow;
321a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport com.android.systemui.statusbar.NotificationContentView;
331a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport com.android.systemui.statusbar.NotificationData;
341a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekimport com.android.systemui.statusbar.phone.StatusBar;
3501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinekimport com.android.systemui.util.Assert;
3601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
3701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinekimport java.util.HashMap;
381a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
391a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek/**
401a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek * A utility that inflates the right kind of contentView based on the state
411a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek */
421a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinekpublic class NotificationInflater {
431a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
4410790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek    @VisibleForTesting
4510790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek    static final int FLAG_REINFLATE_ALL = ~0;
46c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
472630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    @VisibleForTesting
482630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
49c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2;
50c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3;
51c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4;
52c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek
531a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    private final ExpandableNotificationRow mRow;
541a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    private boolean mIsLowPriority;
551a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    private boolean mUsesIncreasedHeight;
561a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    private boolean mUsesIncreasedHeadsUpHeight;
571a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    private RemoteViews.OnClickHandler mRemoteViewClickHandler;
58c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    private boolean mIsChildInGroup;
592630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    private InflationCallback mCallback;
601a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos    private boolean mRedactAmbient;
611a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
621a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    public NotificationInflater(ExpandableNotificationRow row) {
631a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        mRow = row;
641a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
651a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
661a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    public void setIsLowPriority(boolean isLowPriority) {
671a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        mIsLowPriority = isLowPriority;
681a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
691a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
70c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    /**
71c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek     * Set whether the notification is a child in a group
72c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek     *
73c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek     * @return whether the view was re-inflated
74c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek     */
752630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    public void setIsChildInGroup(boolean childInGroup) {
76c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek        if (childInGroup != mIsChildInGroup) {
77c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek            mIsChildInGroup = childInGroup;
78c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek            if (mIsLowPriority) {
792630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek                int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW;
802630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek                inflateNotificationViews(flags);
81c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek            }
822630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        } ;
83c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    }
84c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek
851a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    public void setUsesIncreasedHeight(boolean usesIncreasedHeight) {
861a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        mUsesIncreasedHeight = usesIncreasedHeight;
871a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
881a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
891a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) {
901a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        mUsesIncreasedHeadsUpHeight = usesIncreasedHeight;
911a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
921a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
931a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
941a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        mRemoteViewClickHandler = remoteViewClickHandler;
951a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
961a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
971a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos    public void setRedactAmbient(boolean redactAmbient) {
981a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos        if (mRedactAmbient != redactAmbient) {
991a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos            mRedactAmbient = redactAmbient;
1001a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos            if (mRow.getEntry() == null) {
1011a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos                return;
1021a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos            }
1032630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW);
1041a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos        }
1051a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos    }
1061a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos
1072630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    /**
1082630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek     * Inflate all views of this notification on a background thread. This is asynchronous and will
1092630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek     * notify the callback once it's finished.
1102630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek     */
1112630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    public void inflateNotificationViews() {
112c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek        inflateNotificationViews(FLAG_REINFLATE_ALL);
113c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    }
114c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek
115c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    /**
1162630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek     * Reinflate all views for the specified flags on a background thread. This is asynchronous and
1172630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek     * will notify the callback once it's finished.
1182630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek     *
119c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek     * @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL}
120c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek     *                       to reinflate all of views.
121c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek     */
1222630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    @VisibleForTesting
1232630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    void inflateNotificationViews(int reInflateFlags) {
12410790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        StatusBarNotification sbn = mRow.getEntry().notification;
12501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        new AsyncInflationTask(sbn, reInflateFlags, mRow, mIsLowPriority,
12601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
12701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                mCallback, mRemoteViewClickHandler).execute();
12810790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek    }
1291a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
13010790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek    @VisibleForTesting
13101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    InflationProgress inflateNotificationViews(int reInflateFlags,
13210790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek            Notification.Builder builder, Context packageContext) {
13301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority,
13401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight,
13501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                mRedactAmbient, packageContext);
13601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        apply(result, reInflateFlags, mRow, mRedactAmbient, mRemoteViewClickHandler, null);
13701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        return result;
13801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    }
1391a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos
14001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static InflationProgress createRemoteViews(int reInflateFlags,
14101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup,
14201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
14301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            Context packageContext) {
14401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        InflationProgress result = new InflationProgress();
14501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        isLowPriority = isLowPriority && !isChildInGroup;
14610790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
14701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);
14810790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        }
149c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek
15010790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
15101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            result.newExpandedView = createExpandedView(builder, isLowPriority);
15210790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        }
1531a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
15410790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
15501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight);
15610790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        }
1571a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
15810790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
15901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            result.newPublicView = builder.makePublicContentView();
16010790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        }
16110790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek
16210790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
16301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            result.newAmbientView = redactAmbient ? builder.makePublicAmbientNotification()
1641a1ecfcf5ae32482aee23ebc7c4389daf164caddAdrian Roos                    : builder.makeAmbientNotification();
16501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
16601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        result.packageContext = packageContext;
16701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        return result;
16801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    }
16901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
17001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    public static CancellationSignal apply(InflationProgress result, int reInflateFlags,
17101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            ExpandableNotificationRow row, boolean redactAmbient,
17201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            RemoteViews.OnClickHandler remoteViewClickHandler,
17301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            @Nullable InflationCallback callback) {
17401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        NotificationData.Entry entry = row.getEntry();
17501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        NotificationContentView privateLayout = row.getPrivateLayout();
17601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        NotificationContentView publicLayout = row.getPublicLayout();
17701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        final HashMap<Integer, CancellationSignal> runningInflations = new HashMap<>();
17801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
17901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        int flag = FLAG_REINFLATE_CONTENT_VIEW;
18001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        if ((reInflateFlags & flag) != 0) {
18101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            boolean isNewView = !compareRemoteViews(result.newContentView, entry.cachedContentView);
18201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            ApplyCallback applyCallback = new ApplyCallback() {
18301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                @Override
18401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                public void setResultView(View v) {
18501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    result.inflatedContentView = v;
18601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
18701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
18801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                @Override
18901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                public RemoteViews getRemoteView() {
19001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    return result.newContentView;
19101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
19201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            };
19301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            applyRemoteView(result, reInflateFlags, flag, row, redactAmbient,
19401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    isNewView, remoteViewClickHandler, callback, entry, privateLayout,
19501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    privateLayout.getContractedChild(),
19601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    runningInflations, applyCallback);
19701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
19801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
19901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        flag = FLAG_REINFLATE_EXPANDED_VIEW;
20001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        if ((reInflateFlags & flag) != 0) {
20101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if (result.newExpandedView != null) {
20201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                boolean isNewView = !compareRemoteViews(result.newExpandedView,
20301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        entry.cachedBigContentView);
20401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                ApplyCallback applyCallback = new ApplyCallback() {
20501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    @Override
20601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    public void setResultView(View v) {
20701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        result.inflatedExpandedView = v;
20801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    }
20901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
21001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    @Override
21101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    public RemoteViews getRemoteView() {
21201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        return result.newExpandedView;
21301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    }
21401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                };
21501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                applyRemoteView(result, reInflateFlags, flag, row,
21601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
21701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        privateLayout, privateLayout.getExpandedChild(), runningInflations,
21801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        applyCallback);
21901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
22001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
22101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
22201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        flag = FLAG_REINFLATE_HEADS_UP_VIEW;
22301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        if ((reInflateFlags & flag) != 0) {
22401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if (result.newHeadsUpView != null) {
22501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                boolean isNewView = !compareRemoteViews(result.newHeadsUpView,
22601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        entry.cachedHeadsUpContentView);
22701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                ApplyCallback applyCallback = new ApplyCallback() {
22801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    @Override
22901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    public void setResultView(View v) {
23001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        result.inflatedHeadsUpView = v;
23101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    }
23201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
23301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    @Override
23401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    public RemoteViews getRemoteView() {
23501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        return result.newHeadsUpView;
23601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    }
23701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                };
23801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                applyRemoteView(result, reInflateFlags, flag, row,
23901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
24001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        privateLayout, privateLayout.getHeadsUpChild(), runningInflations,
24101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        applyCallback);
24210790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek            }
2431a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        }
24401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
24501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        flag = FLAG_REINFLATE_PUBLIC_VIEW;
24601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        if ((reInflateFlags & flag) != 0) {
24701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            boolean isNewView = !compareRemoteViews(result.newPublicView,
24801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    entry.cachedPublicContentView);
24901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            ApplyCallback applyCallback = new ApplyCallback() {
25001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                @Override
25101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                public void setResultView(View v) {
25201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    result.inflatedPublicView = v;
25301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
25401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
25501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                @Override
25601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                public RemoteViews getRemoteView() {
25701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    return result.newPublicView;
25801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
25901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            };
26001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            applyRemoteView(result, reInflateFlags, flag, row,
26101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
26201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    publicLayout, publicLayout.getContractedChild(), runningInflations,
26301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    applyCallback);
26401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
26501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
26601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        flag = FLAG_REINFLATE_AMBIENT_VIEW;
26701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        if ((reInflateFlags & flag) != 0) {
26801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout;
26901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            boolean isNewView = !canReapplyAmbient(row, redactAmbient) ||
27001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    !compareRemoteViews(result.newAmbientView, entry.cachedAmbientContentView);
27101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            ApplyCallback applyCallback = new ApplyCallback() {
27201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                @Override
27301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                public void setResultView(View v) {
27401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    result.inflatedAmbientView = v;
27501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
27601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
27701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                @Override
27801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                public RemoteViews getRemoteView() {
27901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    return result.newAmbientView;
28001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
28101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            };
28201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            applyRemoteView(result, reInflateFlags, flag, row,
28301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
28401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    newParent, newParent.getAmbientChild(), runningInflations,
28501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    applyCallback);
28601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
28701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
28801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        // Let's try to finish, maybe nobody is even inflating anything
28901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        finishIfDone(result, reInflateFlags, runningInflations, callback, row,
29001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                redactAmbient);
29101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        CancellationSignal cancellationSignal = new CancellationSignal();
29201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        cancellationSignal.setOnCancelListener(
29301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                () -> runningInflations.values().forEach(CancellationSignal::cancel));
29401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        return cancellationSignal;
29501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    }
29601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
29701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static void applyRemoteView(final InflationProgress result,
29801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            final int reInflateFlags, int inflationId,
29901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            final ExpandableNotificationRow row,
30001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            final boolean redactAmbient, boolean isNewView,
30101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            RemoteViews.OnClickHandler remoteViewClickHandler,
30201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            @Nullable final InflationCallback callback, NotificationData.Entry entry,
30301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            NotificationContentView parentLayout, View existingView,
30401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            final HashMap<Integer, CancellationSignal> runningInflations,
30501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            ApplyCallback applyCallback) {
30601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        RemoteViews.OnViewAppliedListener listener
30701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                = new RemoteViews.OnViewAppliedListener() {
30801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
30901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            @Override
31001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            public void onViewApplied(View v) {
31101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                if (isNewView) {
31201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    v.setIsRootNamespace(true);
31301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    applyCallback.setResultView(v);
31401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
31501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                runningInflations.remove(inflationId);
31601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                finishIfDone(result, reInflateFlags, runningInflations, callback, row,
31701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        redactAmbient);
31801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
31901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
32001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            @Override
32101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            public void onError(Exception e) {
32201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                runningInflations.remove(inflationId);
32301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                handleInflationError(runningInflations, e, entry.notification, callback);
32401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
32501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        };
32601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        CancellationSignal cancellationSignal;
32701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        RemoteViews newContentView = applyCallback.getRemoteView();
32801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        if (isNewView) {
32901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            cancellationSignal = newContentView.applyAsync(
33001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    result.packageContext,
33101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    parentLayout,
33201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    null /* executor */,
33301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    listener,
33401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    remoteViewClickHandler);
33501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        } else {
33601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            cancellationSignal = newContentView.reapplyAsync(
33701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    result.packageContext,
33801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    existingView,
33901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    null /* executor */,
34001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    listener,
34101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    remoteViewClickHandler);
34201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
34301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        runningInflations.put(inflationId, cancellationSignal);
3441a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
3451a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
34601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static void handleInflationError(HashMap<Integer, CancellationSignal> runningInflations,
34701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            Exception e, StatusBarNotification notification, @Nullable InflationCallback callback) {
34801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        Assert.isMainThread();
34901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        runningInflations.values().forEach(CancellationSignal::cancel);
35001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        if (callback != null) {
35101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            callback.handleInflationException(notification, e);
35201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
35301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    }
35401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
35501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    /**
35601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek     * Finish the inflation of the views
35701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek     *
35801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek     * @return true if the inflation was finished
35901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek     */
36001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static boolean finishIfDone(InflationProgress result, int reInflateFlags,
36101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            HashMap<Integer, CancellationSignal> runningInflations,
36201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            @Nullable InflationCallback endListener, ExpandableNotificationRow row,
36301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            boolean redactAmbient) {
36401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        Assert.isMainThread();
36501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        NotificationData.Entry entry = row.getEntry();
36601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        NotificationContentView privateLayout = row.getPrivateLayout();
36701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        NotificationContentView publicLayout = row.getPublicLayout();
36801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        if (runningInflations.isEmpty()) {
36901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
37001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                if (result.inflatedContentView != null) {
37101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    privateLayout.setContractedChild(result.inflatedContentView);
37201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
37301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                entry.cachedContentView = result.newContentView;
37401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
37501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
37601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
37701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                if (result.inflatedExpandedView != null) {
37801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    privateLayout.setExpandedChild(result.inflatedExpandedView);
37901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                } else if (result.newExpandedView == null) {
38001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    privateLayout.setExpandedChild(null);
38101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
38201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                entry.cachedBigContentView = result.newExpandedView;
38301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                row.setExpandable(result.newExpandedView != null);
38401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
38501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
38601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
38701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                if (result.inflatedHeadsUpView != null) {
38801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    privateLayout.setHeadsUpChild(result.inflatedHeadsUpView);
38901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                } else if (result.newHeadsUpView == null) {
39001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    privateLayout.setHeadsUpChild(null);
39101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
39201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                entry.cachedHeadsUpContentView = result.newHeadsUpView;
39301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
39401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
39501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
39601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                if (result.inflatedPublicView != null) {
39701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    publicLayout.setContractedChild(result.inflatedPublicView);
39801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
39901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                entry.cachedPublicContentView = result.newPublicView;
40001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
40101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
40201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
40301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                if (result.inflatedAmbientView != null) {
40401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    NotificationContentView newParent = redactAmbient
40501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                            ? publicLayout : privateLayout;
40601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    NotificationContentView otherParent = !redactAmbient
40701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                            ? publicLayout : privateLayout;
40801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    newParent.setAmbientChild(result.inflatedAmbientView);
40901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    otherParent.setAmbientChild(null);
41001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                }
41101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                entry.cachedAmbientContentView = result.newAmbientView;
41201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
41301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if (endListener != null) {
41401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                endListener.onAsyncInflationFinished(row.getEntry());
41501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
41601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            return true;
41701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
41801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        return false;
41901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    }
42001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
42101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static RemoteViews createExpandedView(Notification.Builder builder,
4221a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek            boolean isLowPriority) {
4231a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        RemoteViews bigContentView = builder.createBigContentView();
4241a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        if (bigContentView != null) {
4251a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek            return bigContentView;
4261a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        }
4271a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        if (isLowPriority) {
4281a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek            RemoteViews contentView = builder.createContentView();
4291a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek            Notification.Builder.makeHeaderExpanded(contentView);
4301a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek            return contentView;
4311a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        }
4321a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        return null;
4331a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
4341a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
43501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static RemoteViews createContentView(Notification.Builder builder,
4361a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek            boolean isLowPriority, boolean useLarge) {
4371a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        if (isLowPriority) {
4381a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek            return builder.makeLowPriorityContentView(false /* useRegularSubtext */);
4391a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        }
4401a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        return builder.createContentView(useLarge);
4411a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
4421a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
4431a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    // Returns true if the RemoteViews are the same.
44401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static boolean compareRemoteViews(final RemoteViews a, final RemoteViews b) {
4451a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        return (a == null && b == null) ||
4461a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek                (a != null && b != null
4471a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek                        && b.getPackage() != null
4481a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek                        && a.getPackage() != null
4491a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek                        && a.getPackage().equals(b.getPackage())
4501a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek                        && a.getLayoutId() == b.getLayoutId());
4511a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
452c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek
4532630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    public void setInflationCallback(InflationCallback callback) {
4542630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        mCallback = callback;
455c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    }
456c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek
4572630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    public interface InflationCallback {
45801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        void handleInflationException(StatusBarNotification notification, Exception e);
4592630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        void onAsyncInflationFinished(NotificationData.Entry entry);
460c478f9023d7649d85e60759c9e6c0e033774293bSelim Cinek    }
46110790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek
4621a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    public void onDensityOrFontScaleChanged() {
4631a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        NotificationData.Entry entry = mRow.getEntry();
4641a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        entry.cachedAmbientContentView = null;
4651a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        entry.cachedBigContentView = null;
4661a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        entry.cachedContentView = null;
4671a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        entry.cachedHeadsUpContentView = null;
4681a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        entry.cachedPublicContentView = null;
4692630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        inflateNotificationViews();
4702630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    }
4712630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek
47201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static boolean canReapplyAmbient(ExpandableNotificationRow row, boolean redactAmbient) {
47301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        NotificationContentView ambientView = redactAmbient ? row.getPublicLayout()
47401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                : row.getPrivateLayout();            ;
47501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        return ambientView.getAmbientChild() != null;
47601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    }
47701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
47801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    public static class AsyncInflationTask extends AsyncTask<Void, Void, InflationProgress>
4790f66a4cc16ec1a927c90ac559c73c80ddcb5ee71Selim Cinek            implements InflationCallback, Abortable {
4802630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek
4812630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        private final StatusBarNotification mSbn;
4822630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        private final Context mContext;
4832630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        private final int mReInflateFlags;
48401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private final boolean mIsLowPriority;
48501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private final boolean mIsChildInGroup;
48601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private final boolean mUsesIncreasedHeight;
48701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private final InflationCallback mCallback;
48801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private final boolean mUsesIncreasedHeadsUpHeight;
48901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private final boolean mRedactAmbient;
49001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private ExpandableNotificationRow mRow;
4912630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        private Exception mError;
49201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private RemoteViews.OnClickHandler mRemoteViewClickHandler;
49301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private CancellationSignal mCancellationSignal;
49401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
49501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private AsyncInflationTask(StatusBarNotification notification,
49601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                int reInflateFlags, ExpandableNotificationRow row, boolean isLowPriority,
49701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                boolean isChildInGroup, boolean usesIncreasedHeight,
49801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
49901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                InflationCallback callback,
50001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                RemoteViews.OnClickHandler remoteViewClickHandler) {
50101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mRow = row;
50201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            NotificationData.Entry entry = row.getEntry();
50301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            entry.setInflationTask(this);
5042630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            mSbn = notification;
5052630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            mReInflateFlags = reInflateFlags;
50601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mContext = mRow.getContext();
50701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mIsLowPriority = isLowPriority;
50801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mIsChildInGroup = isChildInGroup;
50901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mUsesIncreasedHeight = usesIncreasedHeight;
51001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mUsesIncreasedHeadsUpHeight = usesIncreasedHeadsUpHeight;
51101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mRedactAmbient = redactAmbient;
51201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mRemoteViewClickHandler = remoteViewClickHandler;
51301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mCallback = callback;
5142630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        }
5152630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek
5162630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        @Override
51701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        protected InflationProgress doInBackground(Void... params) {
5182630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            try {
5192630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek                final Notification.Builder recoveredBuilder
5202630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek                        = Notification.Builder.recoverBuilder(mContext,
5212630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek                        mSbn.getNotification());
52201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                Context packageContext = mSbn.getPackageContext(mContext);
5235fb73f86299d9cc616ca741f8c7c4af2485cc273Selim Cinek                Notification notification = mSbn.getNotification();
5240847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                if (notification.isMediaNotification()) {
5250847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                    MediaNotificationProcessor processor = new MediaNotificationProcessor(mContext,
52601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                            packageContext);
5270847acd4d48deb716de99d259364bc99b592a8bcSelim Cinek                    processor.setIsLowPriority(mIsLowPriority);
5285fb73f86299d9cc616ca741f8c7c4af2485cc273Selim Cinek                    processor.processNotification(notification, recoveredBuilder);
5295fb73f86299d9cc616ca741f8c7c4af2485cc273Selim Cinek                }
53001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                return createRemoteViews(mReInflateFlags,
53101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        recoveredBuilder, mIsLowPriority, mIsChildInGroup,
53201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
53301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        packageContext);
5342630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            } catch (Exception e) {
5352630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek                mError = e;
5362630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek                return null;
5372630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            }
5382630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        }
5392630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek
5402630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        @Override
54101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        protected void onPostExecute(InflationProgress result) {
5422630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            if (mError == null) {
54301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                mCancellationSignal = apply(result, mReInflateFlags, mRow, mRedactAmbient,
54401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                        mRemoteViewClickHandler, this);
5452630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            } else {
5462630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek                handleError(mError);
5472630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            }
5482630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek        }
5492630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek
55001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private void handleError(Exception e) {
55101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mRow.getEntry().onInflationTaskFinished();
55201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            StatusBarNotification sbn = mRow.getStatusBarNotification();
55301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            final String ident = sbn.getPackageName() + "/0x"
55401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    + Integer.toHexString(sbn.getId());
55501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
55601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mCallback.handleInflationException(sbn,
55701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                    new InflationException("Couldn't inflate contentViews" + e));
55801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
55901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
5600f66a4cc16ec1a927c90ac559c73c80ddcb5ee71Selim Cinek        @Override
56101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        public void abort() {
56201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            cancel(true /* mayInterruptIfRunning */);
56301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            if (mCancellationSignal != null) {
56401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek                mCancellationSignal.cancel();
56501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            }
56601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
56701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
56801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        @Override
56901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        public void handleInflationException(StatusBarNotification notification, Exception e) {
5702630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek            handleError(e);
5711a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek        }
57201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
57301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        @Override
57401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        public void onAsyncInflationFinished(NotificationData.Entry entry) {
57501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mRow.getEntry().onInflationTaskFinished();
57601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mRow.onNotificationUpdated();
57701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek            mCallback.onAsyncInflationFinished(mRow.getEntry());
57801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        }
57901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    }
58001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
58101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private static class InflationProgress {
58201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private RemoteViews newContentView;
58301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private RemoteViews newHeadsUpView;
58401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private RemoteViews newExpandedView;
58501d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private RemoteViews newAmbientView;
58601d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private RemoteViews newPublicView;
58701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
58801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private Context packageContext;
58901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek
59001d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private View inflatedContentView;
59101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private View inflatedHeadsUpView;
59201d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private View inflatedExpandedView;
59301d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private View inflatedAmbientView;
59401d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        private View inflatedPublicView;
5951a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek    }
5961a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek
59701d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek    private abstract static class ApplyCallback {
59801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        public abstract void setResultView(View v);
59901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek        public abstract RemoteViews getRemoteView();
6002630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek    }
6011a48babb5ed30e8a3eb9645355d6455b21041406Selim Cinek}
602