Home | History | Annotate | Download | only in update
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.media.update;
     18 
     19 import android.annotation.Nullable;
     20 import android.content.Context;
     21 import android.content.ContextWrapper;
     22 import android.content.pm.ApplicationInfo;
     23 import android.content.pm.PackageManager.NameNotFoundException;
     24 import android.content.res.Resources;
     25 import android.content.res.Resources.Theme;
     26 import android.content.res.XmlResourceParser;
     27 import android.support.annotation.GuardedBy;
     28 import android.support.v4.widget.Space;
     29 import android.support.v7.widget.ButtonBarLayout;
     30 import android.util.AttributeSet;
     31 import android.view.ContextThemeWrapper;
     32 import android.view.LayoutInflater;
     33 import android.view.View;
     34 import android.view.ViewGroup;
     35 
     36 import com.android.support.mediarouter.app.MediaRouteButton;
     37 import com.android.support.mediarouter.app.MediaRouteExpandCollapseButton;
     38 import com.android.support.mediarouter.app.MediaRouteVolumeSlider;
     39 import com.android.support.mediarouter.app.OverlayListView;
     40 
     41 public final class ApiHelper {
     42     private static ApplicationInfo sUpdatableInfo;
     43 
     44     @GuardedBy("this")
     45     private static Theme sLibTheme;
     46 
     47     private ApiHelper() { }
     48 
     49     static void initialize(ApplicationInfo updatableInfo) {
     50         if (sUpdatableInfo != null) {
     51             throw new IllegalStateException("initialize should only be called once");
     52         }
     53 
     54         sUpdatableInfo = updatableInfo;
     55     }
     56 
     57     public static Resources getLibResources(Context context) {
     58         return getLibTheme(context).getResources();
     59     }
     60 
     61     public static Theme getLibTheme(Context context) {
     62         if (sLibTheme != null) return sLibTheme;
     63 
     64         return getLibThemeSynchronized(context);
     65     }
     66 
     67     public static Theme getLibTheme(Context context, int themeId) {
     68         Theme theme = getLibResources(context).newTheme();
     69         theme.applyStyle(themeId, true);
     70         return theme;
     71     }
     72 
     73     public static LayoutInflater getLayoutInflater(Context context) {
     74         return getLayoutInflater(context, null);
     75     }
     76 
     77     public static LayoutInflater getLayoutInflater(Context context, Theme theme) {
     78         if (theme == null) {
     79             theme = getLibTheme(context);
     80         }
     81 
     82         // TODO (b/72975976): Avoid to use ContextThemeWrapper with app context and lib theme.
     83         LayoutInflater layoutInflater = LayoutInflater.from(context).cloneInContext(
     84                 new ContextThemeWrapper(context, theme));
     85         layoutInflater.setFactory2(new LayoutInflater.Factory2() {
     86             @Override
     87             public View onCreateView(
     88                     View parent, String name, Context context, AttributeSet attrs) {
     89                 if (MediaRouteButton.class.getCanonicalName().equals(name)) {
     90                     return new MediaRouteButton(context, attrs);
     91                 } else if (MediaRouteVolumeSlider.class.getCanonicalName().equals(name)) {
     92                     return new MediaRouteVolumeSlider(context, attrs);
     93                 } else if (MediaRouteExpandCollapseButton.class.getCanonicalName().equals(name)) {
     94                     return new MediaRouteExpandCollapseButton(context, attrs);
     95                 } else if (OverlayListView.class.getCanonicalName().equals(name)) {
     96                     return new OverlayListView(context, attrs);
     97                 } else if (ButtonBarLayout.class.getCanonicalName().equals(name)) {
     98                     return new ButtonBarLayout(context, attrs);
     99                 } else if (Space.class.getCanonicalName().equals(name)) {
    100                     return new Space(context, attrs);
    101                 }
    102                 return null;
    103             }
    104 
    105             @Override
    106             public View onCreateView(String name, Context context, AttributeSet attrs) {
    107                 return onCreateView(null, name, context, attrs);
    108             }
    109         });
    110         return layoutInflater;
    111     }
    112 
    113     public static View inflateLibLayout(Context context, int libResId) {
    114         return inflateLibLayout(context, getLibTheme(context), libResId, null, false);
    115     }
    116 
    117     public static View inflateLibLayout(Context context, Theme theme, int libResId) {
    118         return inflateLibLayout(context, theme, libResId, null, false);
    119     }
    120 
    121     public static View inflateLibLayout(Context context, Theme theme, int libResId,
    122             @Nullable ViewGroup root, boolean attachToRoot) {
    123         try (XmlResourceParser parser = getLibResources(context).getLayout(libResId)) {
    124             return getLayoutInflater(context, theme).inflate(parser, root, attachToRoot);
    125         }
    126     }
    127 
    128     private static synchronized Theme getLibThemeSynchronized(Context context) {
    129         if (sLibTheme != null) return sLibTheme;
    130 
    131         if (sUpdatableInfo == null) {
    132             throw new IllegalStateException("initialize hasn't been called yet");
    133         }
    134 
    135         try {
    136             return sLibTheme = context.getPackageManager()
    137                     .getResourcesForApplication(sUpdatableInfo).newTheme();
    138         } catch (NameNotFoundException e) {
    139             throw new RuntimeException(e);
    140         }
    141     }
    142 }
    143