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