Remove Context requirement from updatable
Bug: 74843539
Test: runtest-cts-MediaComponents && atest VideoView2Test
Change-Id: I1e377435556bdb786322165e3a0563a54bd8fab6
diff --git a/packages/MediaComponents/proguard.cfg b/packages/MediaComponents/proguard.cfg
index 43f2e63..d7bf730 100644
--- a/packages/MediaComponents/proguard.cfg
+++ b/packages/MediaComponents/proguard.cfg
@@ -16,5 +16,5 @@
# Keep entry point for updatable Java classes
-keep public class com.android.media.update.ApiFactory {
- public static java.lang.Object initialize(android.content.res.Resources, android.content.res.Resources$Theme);
+ public static com.android.media.update.ApiFactory initialize(android.content.pm.ApplicationInfo);
}
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
index 395e675..05a54d5 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
@@ -18,8 +18,7 @@
import android.app.Notification;
import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
+import android.content.pm.ApplicationInfo;
import android.media.MediaBrowser2;
import android.media.MediaBrowser2.BrowserCallback;
import android.media.MediaController2;
@@ -83,10 +82,11 @@
import java.util.concurrent.Executor;
-public class ApiFactory implements StaticProvider {
- public static Object initialize(Resources libResources, Theme libTheme)
- throws ReflectiveOperationException {
- ApiHelper.initialize(libResources, libTheme);
+public final class ApiFactory implements StaticProvider {
+ private ApiFactory() { }
+
+ public static ApiFactory initialize(ApplicationInfo updatableInfo) {
+ ApiHelper.initialize(updatableInfo);
return new ApiFactory();
}
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiHelper.java b/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
index 7018844..ad8bb48 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
@@ -19,9 +19,12 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.XmlResourceParser;
+import android.support.annotation.GuardedBy;
import android.support.v4.widget.Space;
import android.support.v7.widget.ButtonBarLayout;
import android.util.AttributeSet;
@@ -35,45 +38,47 @@
import com.android.support.mediarouter.app.MediaRouteVolumeSlider;
import com.android.support.mediarouter.app.OverlayListView;
-public class ApiHelper {
- private static ApiHelper sInstance;
- private final Resources mLibResources;
- private final Theme mLibTheme;
+public final class ApiHelper {
+ private static ApplicationInfo sUpdatableInfo;
- public static ApiHelper getInstance() {
- return sInstance;
- }
+ @GuardedBy("this")
+ private static Theme sLibTheme;
- static void initialize(Resources libResources, Theme libTheme) {
- if (sInstance == null) {
- sInstance = new ApiHelper(libResources, libTheme);
+ private ApiHelper() { }
+
+ static void initialize(ApplicationInfo updatableInfo) {
+ if (sUpdatableInfo != null) {
+ throw new IllegalStateException("initialize should only be called once");
}
+
+ sUpdatableInfo = updatableInfo;
}
- private ApiHelper(Resources libResources, Theme libTheme) {
- mLibResources = libResources;
- mLibTheme = libTheme;
+ public static Resources getLibResources(Context context) {
+ return getLibTheme(context).getResources();
}
- public static Resources getLibResources() {
- return sInstance.mLibResources;
+ public static Theme getLibTheme(Context context) {
+ if (sLibTheme != null) return sLibTheme;
+
+ return getLibThemeSynchronized(context);
}
- public static Theme getLibTheme() {
- return sInstance.mLibTheme;
- }
-
- public static Theme getLibTheme(int themeId) {
- Theme theme = sInstance.mLibResources.newTheme();
+ public static Theme getLibTheme(Context context, int themeId) {
+ Theme theme = getLibResources(context).newTheme();
theme.applyStyle(themeId, true);
return theme;
}
public static LayoutInflater getLayoutInflater(Context context) {
- return getLayoutInflater(context, getLibTheme());
+ return getLayoutInflater(context, null);
}
public static LayoutInflater getLayoutInflater(Context context, Theme theme) {
+ if (theme == null) {
+ theme = getLibTheme(context);
+ }
+
// TODO (b/72975976): Avoid to use ContextThemeWrapper with app context and lib theme.
LayoutInflater layoutInflater = LayoutInflater.from(context).cloneInContext(
new ContextThemeWrapper(context, theme));
@@ -106,7 +111,7 @@
}
public static View inflateLibLayout(Context context, int libResId) {
- return inflateLibLayout(context, getLibTheme(), libResId, null, false);
+ return inflateLibLayout(context, getLibTheme(context), libResId, null, false);
}
public static View inflateLibLayout(Context context, Theme theme, int libResId) {
@@ -115,8 +120,23 @@
public static View inflateLibLayout(Context context, Theme theme, int libResId,
@Nullable ViewGroup root, boolean attachToRoot) {
- try (XmlResourceParser parser = getLibResources().getLayout(libResId)) {
+ try (XmlResourceParser parser = getLibResources(context).getLayout(libResId)) {
return getLayoutInflater(context, theme).inflate(parser, root, attachToRoot);
}
}
+
+ private static synchronized Theme getLibThemeSynchronized(Context context) {
+ if (sLibTheme != null) return sLibTheme;
+
+ if (sUpdatableInfo == null) {
+ throw new IllegalStateException("initialize hasn't been called yet");
+ }
+
+ try {
+ return sLibTheme = context.getPackageManager()
+ .getResourcesForApplication(sUpdatableInfo).newTheme();
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
index fa94a81..fde8a63 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
@@ -130,7 +130,7 @@
mRouter = MediaRouter.getInstance(context);
mCallback = new MediaRouterCallback();
- Resources.Theme theme = ApiHelper.getLibResources().newTheme();
+ Resources.Theme theme = ApiHelper.getLibResources(context).newTheme();
theme.applyStyle(MediaRouterThemeHelper.getRouterThemeId(context), true);
TypedArray a = theme.obtainStyledAttributes(attrs,
R.styleable.MediaRouteButton, defStyleAttr, 0);
@@ -304,7 +304,8 @@
*/
void setCheatSheetEnabled(boolean enable) {
TooltipCompat.setTooltipText(this, enable
- ? ApiHelper.getLibResources().getString(R.string.mr_button_content_description)
+ ? ApiHelper.getLibResources(getContext())
+ .getString(R.string.mr_button_content_description)
: null);
}
@@ -547,7 +548,7 @@
} else {
resId = R.string.mr_cast_button_disconnected;
}
- setContentDescription(ApiHelper.getLibResources().getString(resId));
+ setContentDescription(ApiHelper.getLibResources(getContext()).getString(resId));
}
private final class MediaRouterCallback extends MediaRouter.Callback {
@@ -604,7 +605,7 @@
@Override
protected Drawable doInBackground(Void... params) {
- return ApiHelper.getLibResources().getDrawable(mResId);
+ return ApiHelper.getLibResources(getContext()).getDrawable(mResId);
}
@Override
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
index 6e70eaf..cac64d9 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
@@ -99,8 +99,8 @@
public MediaRouteChooserDialog(Context context, int theme) {
// TODO (b/72975976): Avoid to use ContextThemeWrapper with app context and lib theme.
- super(new ContextThemeWrapper(context,
- ApiHelper.getLibTheme(MediaRouterThemeHelper.getRouterThemeId(context))), theme);
+ super(new ContextThemeWrapper(context, ApiHelper.getLibTheme(context,
+ MediaRouterThemeHelper.getRouterThemeId(context))), theme);
context = getContext();
mRouter = MediaRouter.getInstance(context);
@@ -187,8 +187,8 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(ApiHelper.inflateLibLayout(getContext(),
- ApiHelper.getLibTheme(MediaRouterThemeHelper.getRouterThemeId(getContext())),
+ setContentView(ApiHelper.inflateLibLayout(getContext(), ApiHelper.getLibTheme(getContext(),
+ MediaRouterThemeHelper.getRouterThemeId(getContext())),
R.layout.mr_chooser_dialog));
mRoutes = new ArrayList<>();
@@ -206,7 +206,7 @@
* Sets the width of the dialog. Also called when configuration changes.
*/
void updateLayout() {
- getWindow().setLayout(MediaRouteDialogHelper.getDialogWidth(),
+ getWindow().setLayout(MediaRouteDialogHelper.getDialogWidth(getContext()),
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@@ -263,7 +263,7 @@
public RouteAdapter(Context context, List<MediaRouter.RouteInfo> routes) {
super(context, 0, routes);
- TypedArray styledAttributes = ApiHelper.getLibTheme(
+ TypedArray styledAttributes = ApiHelper.getLibTheme(context,
MediaRouterThemeHelper.getRouterThemeId(context)).obtainStyledAttributes(
new int[] {
R.attr.mediaRouteDefaultIconDrawable,
@@ -294,7 +294,7 @@
View view = convertView;
if (view == null) {
view = ApiHelper.inflateLibLayout(getContext(),
- ApiHelper.getLibTheme(
+ ApiHelper.getLibTheme(getContext(),
MediaRouterThemeHelper.getRouterThemeId(getContext())),
R.layout.mr_chooser_list_item, parent, false);
}
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
index 269a6e9..060cfca 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
@@ -206,8 +206,8 @@
public MediaRouteControllerDialog(Context context, int theme) {
// TODO (b/72975976): Avoid to use ContextThemeWrapper with app context and lib theme.
- super(new ContextThemeWrapper(context,
- ApiHelper.getLibTheme(MediaRouterThemeHelper.getRouterThemeId(context))), theme);
+ super(new ContextThemeWrapper(context, ApiHelper.getLibTheme(context,
+ MediaRouterThemeHelper.getRouterThemeId(context))), theme);
mContext = getContext();
mControllerCallback = new MediaControllerCallback();
@@ -215,7 +215,7 @@
mCallback = new MediaRouterCallback();
mRoute = mRouter.getSelectedRoute();
setMediaSession(mRouter.getMediaSessionToken());
- mVolumeGroupListPaddingTop = ApiHelper.getLibResources().getDimensionPixelSize(
+ mVolumeGroupListPaddingTop = ApiHelper.getLibResources(context).getDimensionPixelSize(
R.dimen.mr_controller_volume_group_list_padding_top);
mAccessibilityManager =
(AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -334,7 +334,7 @@
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
setContentView(ApiHelper.inflateLibLayout(mContext,
- ApiHelper.getLibTheme(MediaRouterThemeHelper.getRouterThemeId(mContext)),
+ ApiHelper.getLibTheme(mContext, MediaRouterThemeHelper.getRouterThemeId(mContext)),
R.layout.mr_controller_material_dialog_b));
// Remove the neutral button.
@@ -359,13 +359,13 @@
int color = MediaRouterThemeHelper.getButtonTextColor(mContext);
mDisconnectButton = findViewById(BUTTON_DISCONNECT_RES_ID);
mDisconnectButton.setText(
- ApiHelper.getLibResources().getString(R.string.mr_controller_disconnect));
+ ApiHelper.getLibResources(mContext).getString(R.string.mr_controller_disconnect));
mDisconnectButton.setTextColor(color);
mDisconnectButton.setOnClickListener(listener);
mStopCastingButton = findViewById(BUTTON_STOP_RES_ID);
mStopCastingButton.setText(
- ApiHelper.getLibResources().getString(R.string.mr_controller_stop_casting));
+ ApiHelper.getLibResources(mContext).getString(R.string.mr_controller_stop_casting));
mStopCastingButton.setTextColor(color);
mStopCastingButton.setOnClickListener(listener);
@@ -440,11 +440,11 @@
}
});
loadInterpolator();
- mGroupListAnimationDurationMs = ApiHelper.getLibResources().getInteger(
+ mGroupListAnimationDurationMs = ApiHelper.getLibResources(mContext).getInteger(
R.integer.mr_controller_volume_group_list_animation_duration_ms);
- mGroupListFadeInDurationMs = ApiHelper.getLibResources().getInteger(
+ mGroupListFadeInDurationMs = ApiHelper.getLibResources(mContext).getInteger(
R.integer.mr_controller_volume_group_list_fade_in_duration_ms);
- mGroupListFadeOutDurationMs = ApiHelper.getLibResources().getInteger(
+ mGroupListFadeOutDurationMs = ApiHelper.getLibResources(mContext).getInteger(
R.integer.mr_controller_volume_group_list_fade_out_duration_ms);
mCustomControlView = onCreateMediaControlView(savedInstanceState);
@@ -460,13 +460,13 @@
* Sets the width of the dialog. Also called when configuration changes.
*/
void updateLayout() {
- int width = MediaRouteDialogHelper.getDialogWidth();
+ int width = MediaRouteDialogHelper.getDialogWidth(mContext);
getWindow().setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT);
View decorView = getWindow().getDecorView();
mDialogContentWidth = width - decorView.getPaddingLeft() - decorView.getPaddingRight();
- Resources res = ApiHelper.getLibResources();
+ Resources res = ApiHelper.getLibResources(mContext);
mVolumeGroupListItemIconSize = res.getDimensionPixelSize(
R.dimen.mr_controller_volume_group_list_item_icon_size);
mVolumeGroupListItemHeight = res.getDimensionPixelSize(
@@ -991,16 +991,16 @@
if (mRoute.getPresentationDisplayId()
!= MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) {
// The user is currently casting screen.
- mTitleView.setText(ApiHelper.getLibResources().getString(
+ mTitleView.setText(ApiHelper.getLibResources(mContext).getString(
R.string.mr_controller_casting_screen));
showTitle = true;
} else if (mState == null || mState.getState() == PlaybackStateCompat.STATE_NONE) {
// Show "No media selected" as we don't yet know the playback state.
- mTitleView.setText(ApiHelper.getLibResources().getString(
+ mTitleView.setText(ApiHelper.getLibResources(mContext).getString(
R.string.mr_controller_no_media_selected));
showTitle = true;
} else if (!hasTitle && !hasSubtitle) {
- mTitleView.setText(ApiHelper.getLibResources().getString(
+ mTitleView.setText(ApiHelper.getLibResources(mContext).getString(
R.string.mr_controller_no_info_available));
showTitle = true;
} else {
@@ -1223,7 +1223,8 @@
AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
event.setPackageName(mContext.getPackageName());
event.setClassName(getClass().getName());
- event.getText().add(ApiHelper.getLibResources().getString(actionDescResId));
+ event.getText().add(
+ ApiHelper.getLibResources(mContext).getString(actionDescResId));
mAccessibilityManager.sendAccessibilityEvent(event);
}
}
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
index 62c050b..9aabf7b 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
@@ -41,12 +41,13 @@
* The framework should set the dialog width properly, but somehow it doesn't work, hence
* duplicating a similar logic here to determine the appropriate dialog width.
*/
- public static int getDialogWidth() {
- DisplayMetrics metrics = ApiHelper.getLibResources().getDisplayMetrics();
+ public static int getDialogWidth(Context context) {
+ DisplayMetrics metrics = ApiHelper.getLibResources(context).getDisplayMetrics();
boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
TypedValue value = new TypedValue();
- ApiHelper.getLibResources().getValue(isPortrait ? R.dimen.mr_dialog_fixed_width_minor
+ ApiHelper.getLibResources(context).getValue(isPortrait
+ ? R.dimen.mr_dialog_fixed_width_minor
: R.dimen.mr_dialog_fixed_width_major, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
return (int) value.getDimension(metrics);
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteExpandCollapseButton.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteExpandCollapseButton.java
index defeedb..6a0a95a 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteExpandCollapseButton.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteExpandCollapseButton.java
@@ -51,9 +51,9 @@
public MediaRouteExpandCollapseButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mExpandAnimationDrawable = (AnimationDrawable)
- ApiHelper.getLibResources().getDrawable(R.drawable.mr_group_expand);
+ ApiHelper.getLibResources(context).getDrawable(R.drawable.mr_group_expand);
mCollapseAnimationDrawable = (AnimationDrawable)
- ApiHelper.getLibResources().getDrawable(R.drawable.mr_group_collapse);
+ ApiHelper.getLibResources(context).getDrawable(R.drawable.mr_group_collapse);
ColorFilter filter = new PorterDuffColorFilter(
MediaRouterThemeHelper.getControllerColor(context, defStyleAttr),
@@ -62,9 +62,9 @@
mCollapseAnimationDrawable.setColorFilter(filter);
mExpandGroupDescription =
- ApiHelper.getLibResources().getString(R.string.mr_controller_expand_group);
+ ApiHelper.getLibResources(context).getString(R.string.mr_controller_expand_group);
mCollapseGroupDescription =
- ApiHelper.getLibResources().getString(R.string.mr_controller_collapse_group);
+ ApiHelper.getLibResources(context).getString(R.string.mr_controller_collapse_group);
setImageDrawable(mExpandAnimationDrawable.getFrame(0));
setContentDescription(mExpandGroupDescription);
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/media/SystemMediaRouteProvider.java b/packages/MediaComponents/src/com/android/support/mediarouter/media/SystemMediaRouteProvider.java
index 33d92b4..a38491f 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/media/SystemMediaRouteProvider.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/media/SystemMediaRouteProvider.java
@@ -267,7 +267,7 @@
mCallbackObj = createCallbackObj();
mVolumeCallbackObj = createVolumeCallbackObj();
- Resources r = ApiHelper.getLibResources();
+ Resources r = ApiHelper.getLibResources(context);
mUserRouteCategoryObj = MediaRouterJellybean.createRouteCategory(
mRouterObj, r.getString(R.string.mr_user_route_category_name), false);
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index 16707c6..1cc407b 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -194,7 +194,7 @@
@Override
public void initialize(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- mResources = ApiHelper.getLibResources();
+ mResources = ApiHelper.getLibResources(mInstance.getContext());
// Inflate MediaControlView2 from XML
mRoot = makeControllerView();
mInstance.addView(mRoot);