package android.app; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.IBinder; import android.os.SystemProperties; import android.util.AndroidRuntimeException; import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; import android.widget.PopupWindow; import android.widget.TextView; import com.android.internal.view.menu.ContextMenuBuilder; import com.tencent.tws.assistant.app.ActionBar; import com.tencent.tws.assistant.app.TwsDialog; import com.tencent.tws.assistant.gaussblur.JNIBlur; import com.tencent.tws.assistant.internal.app.ActionBarImpl; import com.tencent.tws.assistant.internal.view.menu.ListMenuPresenter; import com.tencent.tws.assistant.internal.view.menu.MenuBuilder; import com.tencent.tws.assistant.internal.view.menu.MenuDialogHelper; import com.tencent.tws.assistant.internal.view.menu.MenuPresenter; import com.tencent.tws.assistant.internal.view.menu.MenuView; import com.tencent.tws.assistant.internal.view.menu.StandaloneActionMode; import com.tencent.tws.assistant.internal.widget.ActionBarContainer; import com.tencent.tws.assistant.internal.widget.ActionBarContextView; import com.tencent.tws.assistant.internal.widget.ActionBarView; import com.tencent.tws.assistant.utils.ReflectUtils; import com.tencent.tws.assistant.utils.ResIdentifierUtils; import com.tencent.tws.assistant.utils.ThemeUtils; import com.tencent.tws.sharelib.R; import com.tws.plugin.core.android.TwsActivityInterface; public class TwsActivity extends Activity implements TwsActivityInterface{ private static final String TAG = "TwsActivity"; private static int mStatusBarHeight = 0; private static int mTwsStatusBarHeight = 0; /* package */ActionBarImpl mActionBar = null; ActionBarView mActionBarView = null; private MenuInflater mMenuInflater; ViewGroup mContentParent = null; ViewGroup mPhoneWindowContent = null; TwsContentView mTwsRootView = null;// tws's root view, handle message for // tws View mActivityView = null; private boolean mTitleReady = false; private CharSequence mTitle; private boolean mStatusBarOverlay; private boolean mActionModeOverLayBgIsBlur = false; private Bitmap mTopScreenBlurBitmap = null; private Bitmap mBottomScreenBlurBitmap = null; // DEFAULT IS false, DO NOT MODIFY. private boolean mCustomSplitWhenNarrow = false; private static class ManagedDialog { TwsDialog mDialog; Bundle mArgs; } private SparseArray<ManagedDialog> mManagedDialogs; private boolean mLinearMode; private MenuBuilder mMenu; public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000; // tws-start add for statusbar::2015-1-4 public static final String STATUSBAR_COLOR_WHITE = "black"; public static final String STATUSBAR_COLOR_BLACK = "white"; // tws-end add for statusbar::2015-1-4 private static final boolean IS_SUPPORT_CUSTOM_THEME = true; public static final String KEY_CUSTOM_THEME = "CustomTheme"; // if is setContentView removeOldView must be true,addContentView must be // false private void twsGenerateContentParent() { if (mContentParent == null) { LayoutInflater layoutinflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); boolean hasOverlayActionbar = getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY); boolean hasOverlayActionMode = getWindow().hasFeature(Window.FEATURE_ACTION_MODE_OVERLAY); if (!mLinearMode) { if (hasOverlayActionbar) { mActivityView = layoutinflater.inflate(R.layout.content_action_bar_overlay, null); } else if (hasOverlayActionMode) { mActivityView = layoutinflater.inflate(R.layout.content_overlay_action_mode, null); } else { mActivityView = layoutinflater.inflate(R.layout.content_action_bar, null); } } else { mActivityView = layoutinflater.inflate(R.layout.content_action_bar_linearmode, null); } if (mActivityView == null) { throw new AndroidRuntimeException("twsAddContentView twsActionbar creat fail"); } mContentParent = (ViewGroup) mActivityView.findViewById(android.R.id.content); if (mContentParent == null) { throw new AndroidRuntimeException("twsAddContentView no contenParent"); } mActionBarView = (ActionBarView) mActivityView.findViewById(R.id.tws_action_bar); final int tws_action_bar_height = (int) getResources().getDimension(R.dimen.tws_action_bar_height); mActionBarView .setContentHeight(getResources().getBoolean(R.bool.config_statusbar_state) ? tws_action_bar_height + getStatusBarHeight() : tws_action_bar_height); mActionBarView.setPadding(0, mStatusBarOverlay ? getStatusBarHeight() : 0, 0, 0); // if (mActionBarView == null) { // throw new // AndroidRuntimeException("twsAddContentView no mActionBarView"); // } // make TwsActivity support NoActionBar theme TypedArray a = obtainStyledAttributes(R.styleable.Theme); boolean withActionBar = a.getBoolean(R.styleable.Theme_windowActionBar, true); Log.i(TAG, "withActionBar = " + withActionBar); if (!withActionBar) { mActionBarView.setVisibility(View.GONE); } } else { mContentParent.removeAllViews(); } if (mTwsRootView == null) { mTwsRootView = new TwsContentView(getWindow().getContext()); if (mTwsRootView == null) { throw new AndroidRuntimeException("twsAddContentView mTwsRootView creat fail"); } } else { mTwsRootView.removeAllViews(); } mTwsRootView.addView(mActivityView, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); if (mPhoneWindowContent == null) { mPhoneWindowContent = (ViewGroup) getWindow().getDecorView(); if (mPhoneWindowContent == null) { throw new AndroidRuntimeException("twsAddContentView contentView creat fail"); } } mPhoneWindowContent.removeAllViews(); mPhoneWindowContent.addView(mTwsRootView, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); mActionBarView.setWindowCallback(getWindow().getCallback()); boolean splitActionBar = false; boolean splitWhenNarrow = false; ActivityInfo info = getActivityInfo(); if (info != null) { splitWhenNarrow = (info.uiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0; } if (splitWhenNarrow || mCustomSplitWhenNarrow) { splitActionBar = getResources().getBoolean(R.bool.split_action_bar_is_narrow); } else { splitActionBar = false; } final ActionBarContainer splitView = (ActionBarContainer) mActivityView.findViewById(R.id.tws_split_action_bar); if (splitView != null) { mActionBarView.setSplitView(splitView); mActionBarView.setSplitActionBar(splitActionBar); mActionBarView.setSplitWhenNarrow(splitWhenNarrow); final ActionBarContextView cab = (ActionBarContextView) mActivityView .findViewById(R.id.tws_action_context_bar); cab.setSplitView(splitView); cab.setSplitActionBar(splitActionBar); cab.setSplitWhenNarrow(splitWhenNarrow); } else { Log.e(TAG, "Requested split action bar with " + "incompatible window decor! Ignoring request."); } } public static int getStatusBarHeight() { return mStatusBarHeight == 0 ? mTwsStatusBarHeight : mStatusBarHeight; } private void getSysStatusBarHeight() { if (mStatusBarHeight == 0) { Rect rect = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); mStatusBarHeight = rect.top; if (0 == mStatusBarHeight) { try { Class<?> localClass = Class.forName("com.android.internal.R$dimen"); Object object = localClass.newInstance(); int height = Integer.parseInt(localClass.getField("status_bar_height").get(object).toString()); mStatusBarHeight = getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } } } if (mTwsStatusBarHeight == 0) { mTwsStatusBarHeight = (int) getResources().getDimension(R.dimen.status_bar_height); } } public final ViewGroup getTwsContentView() { if (mContentParent == null) { twsGenerateContentParent(); } return mContentParent; } @Override public void setContentView(int layoutResID) { if (mContentParent == null) { twsGenerateContentParent(); } else { mContentParent.removeAllViews(); } getWindow().getLayoutInflater().inflate(layoutResID, mContentParent); if (getWindow().getCallback() != null && !getWindow().isDestroyed()) { getWindow().getCallback().onContentChanged(); } initActionBar(); } @Override public void setContentView(View view) { setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { if (mContentParent == null) { twsGenerateContentParent(); } else { mContentParent.removeAllViews(); } mContentParent.addView(view, params); if (getWindow().getCallback() != null && !getWindow().isDestroyed()) { getWindow().getCallback().onContentChanged(); } initActionBar(); } @Override public void addContentView(View view, ViewGroup.LayoutParams params) { if (mContentParent == null) { twsGenerateContentParent(); } mContentParent.addView(view, params); if (getWindow().getCallback() != null && !getWindow().isDestroyed()) { getWindow().getCallback().onContentChanged(); } initActionBar(); } @Override public void onDetachedFromWindow() { if (mActionBarView != null) { mActionBarView.dismissPopupMenus(); } super.onDetachedFromWindow(); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); if (!isChild()) { mTitleReady = true; onTitleChanged(getTitle(), getTitleColor()); } } @Override protected void onTitleChanged(CharSequence title, int color) { super.onTitleChanged(title, color); if (mTitleReady) { final Window win = getWindow(); if (win != null) { win.setTitle(title); if (mActionBarView != null) { mActionBarView.setWindowTitle(title); } } } } @Override public void setTitle(CharSequence title) { mTitle = title; onTitleChanged(title, getTitleColor()); super.setTitle(title); } @Override public void setTitle(int titleId) { setTitle(getText(titleId)); } private void initActionBar() { ViewGroup twsContentView = getTwsContentView(); if (mActionBar == null) { mActionBar = new ActionBarImpl(this, mStatusBarOverlay); } if (mActionBarView != null) { mActionBarView.setWindowTitle(getTitle()); } } public ActionBar getTwsActionBar() { initActionBar(); return mActionBar; } public boolean onMenuOpened(int featureId, Menu menu) { if (featureId == Window.FEATURE_ACTION_BAR) { initActionBar(); if (mActionBar != null) { mActionBar.dispatchMenuVisibilityChanged(true); } else { Log.e(TAG, "Tried to open action bar menu with no action bar"); } } return true; } public void onPanelClosed(int featureId, Menu menu) { mActionBar.dispatchMenuVisibilityChanged(false); super.onPanelClosed(featureId, menu); } public MenuInflater getMenuInflater() { // Make sure that action views can get an appropriate theme. if (mMenuInflater == null) { initActionBar(); if (mActionBar != null) { mMenuInflater = new MenuInflater(mActionBar.getThemedContext()); } else { mMenuInflater = new MenuInflater(this); } } return mMenuInflater; } public ActionMode startActionMode(ActionMode.Callback callback) { return mTwsRootView.startActionMode(callback); } @Override public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) { initActionBar(); if (mActionBar != null) { if (mActionBarView != null && !mActionBarView.mIsMarksPointFlag) { invalidateOptionsMenu(); } return mActionBar.startActionMode(callback); } return null; } @Override public boolean onCreatePanelMenu(int featureId, Menu menu) { getMenu().clear(); return super.onCreatePanelMenu(featureId, menu); } @Override public boolean onPreparePanel(int featureId, View view, Menu menu) { filterMenu(menu); return super.onPreparePanel(featureId, view, menu); } @Override protected void onStop() { super.onStop(); closePopupMenu();// panel menu closeContextMenu();// context menu } void filterMenu(Menu menu) { mMenu.setCallback(mMenuCallback); if (mActionBarView != null) { mActionBarView.setMenu(mMenu, null); } } public Menu getMenu() { if (mMenu == null) { mMenu = new MenuBuilder(this); } return mMenu; } protected void onCreate(Bundle savedInstanceState) { if (android.os.Build.VERSION.SDK_INT > 18 && getResources().getBoolean(R.bool.config_statusbar_state)) { Window window = getWindow(); window.addFlags(FLAG_TRANSLUCENT_STATUS); setStatusBarOverlay(); } requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); getSysStatusBarHeight(); } protected void onResume() { super.onResume(); boolean isThemeChanged = false; boolean isDefaultTheme = SystemProperties.getBoolean("persist.sys.theme", true); if (!isDefaultTheme) { ActivityInfo info = getActivityInfo(); if (info != null) { isThemeChanged = false; } else { isThemeChanged = false; } } invalidateOptionsMenu(); ActionBar actionBar = getTwsActionBar(); if (actionBar != null && android.os.Build.VERSION.SDK_INT > 18) { String customColor = changeTwsStatusBarColor(); if (customColor != null) { if (STATUSBAR_COLOR_WHITE.equals(customColor)) { sendStatusBarBroadcast(STATUSBAR_COLOR_WHITE, isThemeChanged); } else if (STATUSBAR_COLOR_BLACK.equals(customColor)) { sendStatusBarBroadcast(STATUSBAR_COLOR_BLACK, isThemeChanged); } else { sendStatusBarBroadcast(STATUSBAR_COLOR_BLACK, isThemeChanged); } } else { int id = actionBar.getBackgroundResId(); if (id == R.drawable.ab_solid_holo_light) { if (ThemeUtils.isActionBarBackgroundGradient(this)) { sendStatusBarBroadcast(STATUSBAR_COLOR_WHITE, isThemeChanged); } else { sendStatusBarBroadcast(STATUSBAR_COLOR_BLACK, isThemeChanged); } } else if (id == R.drawable.ab_solid_holo_dark) { sendStatusBarBroadcast(STATUSBAR_COLOR_WHITE, isThemeChanged); } } } else { String color = changeTwsStatusBarColor(); if (null != color && STATUSBAR_COLOR_WHITE.equals(color)) { sendStatusBarBroadcast(STATUSBAR_COLOR_WHITE, isThemeChanged); } else if (null != color && STATUSBAR_COLOR_BLACK.equals(color)) { sendStatusBarBroadcast(STATUSBAR_COLOR_BLACK, isThemeChanged); } else { sendStatusBarBroadcast(STATUSBAR_COLOR_WHITE, isThemeChanged); } } } protected void onPause() { super.onPause(); if (mActionBarView != null && mActionBarView.mIsMarksPointFlag) { closePopupMenu();// panel menu } } MenuBuilder.Callback mMenuCallback = new MenuBuilder.Callback() { public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { boolean result = TwsActivity.this.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item); closePopupMenu(); return result; } public void onMenuModeChange(MenuBuilder menu) { if (!mPopupMenuShow && !mActionBar.isMultiMode()) { onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, getMenu()); } } }; public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub switch (keyCode) { case KeyEvent.KEYCODE_MENU: if (event.getRepeatCount() == 0 && !mPopupMenuShow && !mActionBar.isMultiMode()) { if (onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, getMenu()) == false) return true; } return true; } return super.onKeyDown(keyCode, event); } public boolean onKeyUp(int keyCode, KeyEvent event) { // TODO Auto-generated method stub switch (keyCode) { case KeyEvent.KEYCODE_MENU: { if (mActionBarView != null && mActionBarView.isOverflowReserved() && mActionBar.mOverflowButtonState) { if (mActionBarView.getVisibility() == View.VISIBLE && mActionBarView.isOverflowButtonShowing()) { if (!mActionBarView.isOverflowMenuShowing()) { if (!isDestroyed() && onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, getMenu())) { mActionBarView.showOverflowMenu(); } } else { mActionBarView.hideOverflowMenu(); } } } return true; } } return super.onKeyUp(keyCode, event); } @Override public boolean dispatchKeyEvent(KeyEvent event) { // for actionmod if (mTwsRootView.superDispatchKeyEvent(event)) { return true; } return super.dispatchKeyEvent(event); } private void closePopupMenu() { WindowManager wm = this.getWindowManager(); if (wm == null) { return; } if (mPopupViewContainer != null && mPopupMenuShow) { wm.removeView(mPopupViewContainer); mPopupMenuShow = false; } if (mActionBarView != null) { mActionBarView.hideOverflowMenu(); } } PopupViewContainer getPopupViewContainer() { if (mPopupViewContainer == null) { mPopupViewContainer = new PopupViewContainer(this); mPopupViewContainer.setBackgroundResource(R.drawable.transparent_background); } return mPopupViewContainer; } private WindowManager.LayoutParams createPopupLayout(/* IBinder token */) { WindowManager wm = this.getWindowManager(); if (wm == null) { return null; } int width = wm.getDefaultDisplay().getWidth(); int height = wm.getDefaultDisplay().getHeight(); WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; lp.width = width; lp.height = WindowManager.LayoutParams.WRAP_CONTENT; lp.format = getPopupViewContainer().getBackground().getOpacity(); lp.flags = WindowManager.LayoutParams.FLAG_DITHER | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH | WindowManager.LayoutParams.FLAG_DIM_BEHIND; lp.gravity = Gravity.CENTER | Gravity.BOTTOM; lp.dimAmount = 0.6f; lp.windowAnimations = R.style.Animation_DropDownUp_tws; return lp; } ListMenuPresenter mListMenuPresenter = new ListMenuPresenter(R.layout.popup_menu_item_layout, R.style.Theme_tws_CompactMenu_Second); MenuView mMenuView; PopupViewContainer mPopupViewContainer; boolean mPopupMenuShow = false; private class PopupViewContainer extends FrameLayout { private static final String TAG = "PopupWindow.PopupViewContainer"; public PopupViewContainer(Context context) { super(context); } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK || event.getKeyCode() == KeyEvent.KEYCODE_MENU) { if (getKeyDispatcherState() == null) { return super.dispatchKeyEvent(event); } if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { KeyEvent.DispatcherState state = getKeyDispatcherState(); if (state != null) { state.startTracking(event, this); } return true; } else if (event.getAction() == KeyEvent.ACTION_UP) { KeyEvent.DispatcherState state = getKeyDispatcherState(); if (state != null && state.isTracking(event) && !event.isCanceled()) { closePopupMenu(); return true; } } return super.dispatchKeyEvent(event); } else { return super.dispatchKeyEvent(event); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); if ((event.getAction() == MotionEvent.ACTION_DOWN) && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) { closePopupMenu(); return true; } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { closePopupMenu(); return true; } else { return super.onTouchEvent(event); } } } @Override public void invalidateOptionsMenu() { super.invalidateOptionsMenu(); onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, getMenu()); onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, getMenu()); } @Override public void closeContextMenu() { super.closeContextMenu(); if (mContextMenu != null) { mContextMenu.close(); dismissContextMenu(); } } private synchronized void dismissContextMenu() { mContextMenu = null; if (mContextMenuHelper != null) { mContextMenuHelper.dismiss(); mContextMenuHelper = null; } } final DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(Window.FEATURE_CONTEXT_MENU); private ContextMenuBuilder mContextMenu; private MenuDialogHelper mContextMenuHelper; // getCallback is activity public final class TwsContentView extends FrameLayout { private ActionMode mActionMode; private ActionBarContextView mActionModeView; private PopupWindow mActionModePopup; private Runnable mShowActionModePopup; private View twsmOriginalView = null; public TwsContentView(Context context) { super(context); } public boolean superDispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { final int action = event.getAction(); // Back cancels action modes first. if (mActionMode != null) { if (action == KeyEvent.ACTION_UP) { mActionMode.finish(); } return true; } // Next collapse any expanded action views. if (mActionBarView != null && mActionBarView.hasExpandedActionView()) { if (action == KeyEvent.ACTION_UP) { mActionBarView.collapseActionView(); } return true; } } return false; } public View twsGetOriginalView() { return twsmOriginalView; } void twsActionModPopWindow(ActionMode mode, ActionMode.Callback callback) { boolean creatValue = callback.onCreateActionMode(mode, mode.getMenu()); // this is textview if (twsGetOriginalView() instanceof TextView) { mode.invalidate(); mActionMode = mode; } else { if (creatValue) { mode.invalidate(); mActionModeView.initForMode(mode); mActionModeView.setVisibility(View.VISIBLE); mActionMode = mode; if (mActionModePopup != null) { post(mShowActionModePopup); } mActionModeView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } else { mActionMode = null; } } } void twsMakeSureContextView() { // must have this, other actionmod finish will crash if ((twsmOriginalView instanceof TextView) && mActionModeView == null) { mActionModeView = new ActionBarContextView(mContext); } } private ActionMode twsStartActionModeForChild(View originalView, ActionMode.Callback callback) { twsmOriginalView = originalView; if (mActionMode != null) { mActionMode.finish(); } final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); ActionMode mode = null; if (!(twsmOriginalView instanceof TextView)) { if (getWindow().getCallback() != null && !getWindow().isDestroyed()) { try { mode = getWindow().getCallback().onWindowStartingActionMode(wrappedCallback); } catch (AbstractMethodError ame) { // Older apps might not implement this callback method. } } } if (mode != null) { mActionMode = mode; } else { if (mActionModeView == null) { if (getWindow().isFloating()) { mActionModeView = new ActionBarContextView(mContext); mActionModePopup = new PopupWindow(mContext, null, R.attr.actionModePopupWindowStyle); mActionModePopup.setLayoutInScreenEnabled(true); mActionModePopup.setLayoutInsetDecor(true); mActionModePopup.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION); mActionModePopup.setContentView(mActionModeView); mActionModePopup.setWidth(MATCH_PARENT); TypedValue heightValue = new TypedValue(); mContext.getTheme().resolveAttribute(android.R.attr.actionBarSize, heightValue, true); final int height = TypedValue.complexToDimensionPixelSize(heightValue.data, mContext .getResources().getDisplayMetrics()); mActionModeView.setContentHeight(height); mActionModePopup.setHeight(WRAP_CONTENT); mShowActionModePopup = new Runnable() { public void run() { mActionModePopup.showAtLocation(mActionModeView.getApplicationWindowToken(), Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); } }; } } twsMakeSureContextView(); if (mActionModeView != null) { mActionModeView.killMode(); mode = new StandaloneActionMode(getContext(), mActionModeView, wrappedCallback, mActionModePopup == null); twsActionModPopWindow(mode, callback); } } if (mActionMode != null && getWindow().getCallback() != null && !getWindow().isDestroyed()) { try { getWindow().getCallback().onActionModeStarted(mActionMode); } catch (AbstractMethodError ame) { // Older apps might not implement this callback method. } } return mActionMode; } @Override public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) { return twsStartActionModeForChild(originalView, callback); } @Override public ActionMode startActionMode(ActionMode.Callback callback) { if (mActionMode != null) { mActionMode.finish(); } final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); ActionMode mode = null; if (getWindow().getCallback() != null && !getWindow().isDestroyed()) { try { mode = getWindow().getCallback().onWindowStartingActionMode(wrappedCallback); } catch (AbstractMethodError ame) { // Older apps might not implement this callback method. } } if (mode != null) { mActionMode = mode; } else { if (mActionModeView == null) { if (getWindow().isFloating()) { mActionModeView = new ActionBarContextView(mContext); mActionModePopup = new PopupWindow(mContext, null, R.attr.actionModePopupWindowStyle); mActionModePopup.setLayoutInScreenEnabled(true); mActionModePopup.setLayoutInsetDecor(true); mActionModePopup.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION); mActionModePopup.setContentView(mActionModeView); mActionModePopup.setWidth(MATCH_PARENT); TypedValue heightValue = new TypedValue(); mContext.getTheme().resolveAttribute(android.R.attr.actionBarSize, heightValue, true); final int height = TypedValue.complexToDimensionPixelSize(heightValue.data, mContext .getResources().getDisplayMetrics()); mActionModeView.setContentHeight(height); mActionModePopup.setHeight(WRAP_CONTENT); mShowActionModePopup = new Runnable() { public void run() { mActionModePopup.showAtLocation(mActionModeView.getApplicationWindowToken(), Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); } }; } else { int stubID = ResIdentifierUtils.getSysId("action_mode_bar_stub"); if (0 != stubID) { ViewStub stub = (ViewStub) findViewById(stubID); if (stub != null) { mActionModeView = (ActionBarContextView) stub.inflate(); } } } } if (mActionModeView != null) { mActionModeView.killMode(); mode = new StandaloneActionMode(getContext(), mActionModeView, wrappedCallback, mActionModePopup == null); if (callback.onCreateActionMode(mode, mode.getMenu())) { mode.invalidate(); mActionModeView.initForMode(mode); mActionModeView.setVisibility(View.VISIBLE); mActionMode = mode; if (mActionModePopup != null) { post(mShowActionModePopup); } mActionModeView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } else { mActionMode = null; } } } if (mActionMode != null && getWindow().getCallback() != null && !getWindow().isDestroyed()) { try { getWindow().getCallback().onActionModeStarted(mActionMode); } catch (AbstractMethodError ame) { // Older apps might not implement this callback method. } } boolean hasOverlayActionMode = getWindow().hasFeature(Window.FEATURE_ACTION_MODE_OVERLAY); if (hasOverlayActionMode && mActionModeOverLayBgIsBlur) { try { mBottomScreenBlurBitmap = takeSplitActionBarBlur(TwsActivity.this); if (mBottomScreenBlurBitmap != null && !mBottomScreenBlurBitmap.isRecycled()) { mActionBar.setSplitBackgroundDrawable(new BitmapDrawable(mBottomScreenBlurBitmap)); } } catch (Exception e) { e.printStackTrace(); } } return mActionMode; } private class ActionModeCallbackWrapper implements ActionMode.Callback { private ActionMode.Callback mWrapped; public ActionModeCallbackWrapper(ActionMode.Callback wrapped) { mWrapped = wrapped; } public boolean onCreateActionMode(ActionMode mode, Menu menu) { return mWrapped.onCreateActionMode(mode, menu); } public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return mWrapped.onPrepareActionMode(mode, menu); } public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return mWrapped.onActionItemClicked(mode, item); } public void onDestroyActionMode(ActionMode mode) { mWrapped.onDestroyActionMode(mode); if (mActionModePopup != null) { removeCallbacks(mShowActionModePopup); mActionModePopup.dismiss(); } else if (mActionModeView != null) { mActionModeView.setVisibility(GONE); } if (mActionModeView != null) { mActionModeView.removeAllViews(); } if (getWindow().getCallback() != null && !getWindow().isDestroyed()) { try { getWindow().getCallback().onActionModeFinished(mActionMode); } catch (AbstractMethodError ame) { // Older apps might not implement this callback method. } } mActionMode = null; } } } private final class DialogMenuCallback implements MenuBuilder.Callback, MenuPresenter.Callback { private int mFeatureId; private MenuDialogHelper mSubMenuHelper; public DialogMenuCallback(int featureId) { mFeatureId = featureId; } public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { if (menu.getRootMenu() != menu) { onCloseSubMenu(menu); } if (allMenusAreClosing) { Window.Callback callback = getWindow().getCallback(); if (callback != null && !getWindow().isDestroyed()) { callback.onPanelClosed(mFeatureId, menu); } // Dismiss the submenu, if it is showing if (mSubMenuHelper != null) { mSubMenuHelper.dismiss(); mSubMenuHelper = null; } } } public void onCloseSubMenu(MenuBuilder menu) { Window.Callback callback = getWindow().getCallback(); if (callback != null && !getWindow().isDestroyed()) { callback.onPanelClosed(mFeatureId, menu.getRootMenu()); } } public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { Window.Callback callback = getWindow().getCallback(); return (callback != null && !getWindow().isDestroyed()) && callback.onMenuItemSelected(mFeatureId, item); } public void onMenuModeChange(MenuBuilder menu) { } public boolean onOpenSubMenu(MenuBuilder subMenu) { if (subMenu == null) return false; // Set a simple callback for the submenu subMenu.setCallback(this); // The window manager will give us a valid window token mSubMenuHelper = new MenuDialogHelper(subMenu); mSubMenuHelper.show(null); return true; } } private ActivityInfo getActivityInfo() { ActivityInfo info = null; try { info = twsGetPackageManager().getActivityInfo(this.getComponentName(), PackageManager.GET_ACTIVITIES); } catch (Exception e) { e.printStackTrace(); return null; } return info; } private PackageManager twsGetPackageManager() { PackageManager pm = this.getPackageManager(); if (pm == null) { resetIPackageManager(this); pm = this.getPackageManager(); } return pm; } public void resetIPackageManager(Context context) { Context contextImpl; if (context instanceof ContextWrapper) { contextImpl = ((ContextWrapper) context).getBaseContext(); } else { return; } try { Class<?> clazz1 = ReflectUtils.forClassName("android.app.ActivityThread"); Field field1 = ReflectUtils.getDeclaredField(clazz1, "sPackageManager"); ReflectUtils.setFieldValue(null, field1, null); Class<?> clazz2 = ReflectUtils.forClassName("android.app.ContextImpl"); Field field2 = ReflectUtils.getDeclaredField(clazz2, "mPackageManager"); ReflectUtils.setFieldValue(contextImpl, field2, null); Class<?> clazz3 = ReflectUtils.forClassName("android.os.ServiceManager"); Field field3 = ReflectUtils.getDeclaredField(clazz3, "sServiceManager"); ReflectUtils.setFieldValue(null, field3, null); HashMap<String, IBinder> map = (HashMap<String, IBinder>) ReflectUtils .getFieldValue("sCache", null, clazz3); if (map != null) { IBinder oldValue = map.remove("package"); if (oldValue != null) { Method method1 = ReflectUtils.getDeclaredMethod(clazz3, "getService", String.class); IBinder newValue = (IBinder) ReflectUtils.invoke(method1, null, "package"); if (newValue != null) { map.put("package", newValue); } } } } catch (Exception e) { e.printStackTrace(); } } private TwsDialog createTwsDialog(Integer dialogId, Bundle state, Bundle args) { final TwsDialog dialog = onCreateTwsDialog(dialogId, args); if (dialog == null) { return null; } dialog.dispatchOnCreate(state); return dialog; } @Override protected void onDestroy() { super.onDestroy(); // dismiss any dialogs we are managing. if (mManagedDialogs != null) { final int numDialogs = mManagedDialogs.size(); for (int i = 0; i < numDialogs; i++) { final ManagedDialog md = mManagedDialogs.valueAt(i); if (md.mDialog.isShowing()) { md.mDialog.dismiss(); } } mManagedDialogs = null; } if (mActionModeOverLayBgIsBlur) { try { if (mBottomScreenBlurBitmap != null && !mBottomScreenBlurBitmap.isRecycled()) { mBottomScreenBlurBitmap.recycle(); mBottomScreenBlurBitmap = null; Log.d(TAG, "onDestroy() mBottomScreenBlurBitmap"); } } catch (Exception e) { e.printStackTrace(); } } } public final boolean showTwsDialog(int id, Bundle args) { if (mManagedDialogs == null) { mManagedDialogs = new SparseArray<ManagedDialog>(); } ManagedDialog md = mManagedDialogs.get(id); if (md == null) { md = new ManagedDialog(); md.mDialog = createTwsDialog(id, null, args); if (md.mDialog == null) { return false; } mManagedDialogs.put(id, md); } md.mArgs = args; onPrepareTwsDialog(id, md.mDialog, args); md.mDialog.show(); return true; } public final void dismissTwsDialog(int id) { if (mManagedDialogs == null) { throw missingTwsDialog(id); } final ManagedDialog md = mManagedDialogs.get(id); if (md == null) { throw missingTwsDialog(id); } md.mDialog.dismiss(); } private IllegalArgumentException missingTwsDialog(int id) { return new IllegalArgumentException("no dialog with id " + id + " was ever " + "shown via Activity#showDialog"); } public final void removeTwsDialog(int id) { if (mManagedDialogs != null) { final ManagedDialog md = mManagedDialogs.get(id); if (md != null) { md.mDialog.dismiss(); mManagedDialogs.remove(id); } } } public final void showTwsDialog(int id) { showTwsDialog(id, null); } protected TwsDialog onCreateTwsDialog(int id) { return null; } protected TwsDialog onCreateTwsDialog(int id, Bundle args) { return onCreateTwsDialog(id); } protected void onPrepareTwsDialog(int id, TwsDialog dialog) { dialog.setBottomButtonsStartAnimation(true); dialog.setOwnerActivity(this); } protected void onPrepareTwsDialog(int id, TwsDialog dialog, Bundle args) { onPrepareTwsDialog(id, dialog); } public void sendStatusBarBroadcast(String color, boolean isThemeChanged) { Intent status_intent = new Intent(); status_intent.setPackage("com.android.systemui"); status_intent.setAction("tws.systemui.statusbar.theme"); status_intent.putExtra("color", color); status_intent.putExtra("isThemeChanged", isThemeChanged); // agneswang 20150310 send the window params of the activity to SystemUI status_intent.putExtra("windowType", getWindow().getAttributes().type); status_intent.putExtra("windowFlag", getWindow().getAttributes().flags); sendBroadcast(status_intent); } public void setStatusBarOverlay() { mStatusBarOverlay = true; } public void setActionModeOverLayBgBlur(boolean isBlur) { mActionModeOverLayBgIsBlur = isBlur; } public Bitmap takeSplitActionBarBlur(Activity activity) { try { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bitmap = view.getDrawingCache(); Rect rect = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); int statusBarHeight = rect.top; int width = activity.getWindowManager().getDefaultDisplay().getWidth(); int height = activity.getWindowManager().getDefaultDisplay().getHeight(); int bottomHeight = getResources().getDimensionPixelSize(R.dimen.tws_actionbar_split_height); Drawable bottomDrawable = getResources().getDrawable(R.drawable.ab_solid_holo_light_bottom); bottomDrawable.setBounds(0, 0, width, bottomHeight); Matrix matrix = new Matrix(); matrix.postScale(0.2f, 0.2f); Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, height - bottomHeight, width, bottomHeight, matrix, true); Canvas canvas = new Canvas(bitmap2); bottomDrawable.draw(canvas); canvas.save(Canvas.ALL_SAVE_FLAG); canvas.restore(); view.destroyDrawingCache(); JNIBlur blur = new JNIBlur(TwsActivity.this); Bitmap bitmap3 = blur.blur(bitmap2, true); return bitmap3; } catch (Exception e) { e.printStackTrace(); return null; } } public Bitmap takeActionBarBlur(Activity activity) { try { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bitmap = view.getDrawingCache(); Rect rect = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); int statusBarHeight = rect.top; int width = activity.getWindowManager().getDefaultDisplay().getWidth(); int height = activity.getWindowManager().getDefaultDisplay().getHeight(); int topHeight = getResources().getDimensionPixelSize(R.dimen.tws_action_bar_height) - getStatusBarHeight(); Drawable topDrawable = getResources().getDrawable(R.drawable.ab_solid_holo_light); topDrawable.setBounds(0, 0, width, topHeight); Matrix matrix = new Matrix(); matrix.postScale(0.2f, 0.2f); Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, 0, width, topHeight, matrix, true); Canvas canvas = new Canvas(bitmap2); topDrawable.draw(canvas); canvas.save(Canvas.ALL_SAVE_FLAG); canvas.restore(); view.destroyDrawingCache(); JNIBlur blur = new JNIBlur(TwsActivity.this); Bitmap bitmap3 = blur.blur(bitmap2, true); return bitmap3; } catch (Exception e) { e.printStackTrace(); return null; } } public void setLinearMode(boolean linearMode) { this.mLinearMode = linearMode; } // tws-start add for statusbar::2015-1-4 public String changeTwsStatusBarColor() { return null; } @Deprecated public void setHoloStatusBar() { } // tws-end add for statusbar::2015-1-4 private void useCustomTheme() { if (IS_SUPPORT_CUSTOM_THEME) { Intent intent = getIntent(); if (intent != null) { Bundle bundle = intent.getExtras(); if (bundle != null) { int customTheme = bundle.getInt(KEY_CUSTOM_THEME, 0); if (customTheme != 0) { setTheme(customTheme); } } } } } // only before before setContentView valid @Override public void setSplitActionWhenNarrowOptions(boolean isSplitActionWhenNarrow) { if (mContentParent != null) { Log.e(TAG, "该接口只能在调用setContent/getTwsActionBar/getTwsContentView之前使用才有效~"); throw new IllegalAccessError("Only before before init mContentParent valid!"); } mCustomSplitWhenNarrow = isSplitActionWhenNarrow; } }