1/* 2 * Copyright (C) 2017 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 17package com.android.layoutlib.bridge.remote.server; 18 19import com.android.ide.common.rendering.api.DrawableParams; 20import com.android.ide.common.rendering.api.RenderParams; 21import com.android.ide.common.rendering.api.Result; 22import com.android.ide.common.rendering.api.SessionParams; 23import com.android.layout.remote.api.RemoteBridge; 24import com.android.layout.remote.api.RemoteDrawableParams; 25import com.android.layout.remote.api.RemoteLayoutLog; 26import com.android.layout.remote.api.RemoteRenderParams; 27import com.android.layout.remote.api.RemoteRenderSession; 28import com.android.layout.remote.api.RemoteSessionParams; 29import com.android.layoutlib.bridge.Bridge; 30import com.android.layoutlib.bridge.remote.server.adapters.RemoteAssetRepositoryAdapter; 31import com.android.layoutlib.bridge.remote.server.adapters.RemoteILayoutPullParserAdapter; 32import com.android.layoutlib.bridge.remote.server.adapters.RemoteLayoutLogAdapter; 33import com.android.layoutlib.bridge.remote.server.adapters.RemoteLayoutlibCallbackAdapter; 34import com.android.layoutlib.bridge.remote.server.adapters.RemoteRenderResourcesAdapter; 35import com.android.layoutlib.bridge.remote.server.adapters.RemoteRenderSessionAdapter; 36import com.android.tools.layoutlib.annotations.NotNull; 37 38import java.io.File; 39import java.rmi.RemoteException; 40import java.util.HashMap; 41import java.util.HashSet; 42import java.util.Map; 43import java.util.Set; 44 45/** 46 * Remote {@link Bridge} implementation. This class is the remote entry point for the server. Its 47 * responsibility is to receive the remote calls and apply the required transformations to convert 48 * it into a regular call to the {@link Bridge} class. 49 */ 50public class RemoteBridgeImpl implements RemoteBridge { 51 private Bridge mBridge = new Bridge(); 52 53 /** 54 * The project keys are used as key for some caches. They are usually expected to remain in 55 * memory so WeakReferences are used in the caches. 56 * Because in the remote bridge we do not have a real pointer to the object, we keep the strings 57 * in memory until they are cleared. 58 */ 59 private Map<String, String> mCachedProjectKeys = new HashMap<>(); 60 61 @Override 62 public int getApiLevel() { 63 return mBridge.getApiLevel(); 64 } 65 66 @Override 67 public int getRevision() { 68 return mBridge.getRevision(); 69 } 70 71 @Override 72 public boolean supports(int feature) { 73 return mBridge.supports(feature); 74 } 75 76 @Override 77 public boolean init(Map<String, String> platformProperties, File fontLocation, 78 Map<String, Map<String, Integer>> enumValueMap, RemoteLayoutLog log) { 79 return mBridge.init(platformProperties, fontLocation, enumValueMap, 80 log != null ? new RemoteLayoutLogAdapter(log) : null); 81 } 82 83 @Override 84 public boolean dispose() { 85 return mBridge.dispose(); 86 } 87 88 private static void setupRenderParams(@NotNull RenderParams params, 89 @NotNull RemoteRenderParams remoteParams) throws RemoteException { 90 params.setAssetRepository(new RemoteAssetRepositoryAdapter(remoteParams.getAssets())); 91 params.setActivityName(remoteParams.getActivityName()); 92 params.setAppIcon(remoteParams.getAppIcon()); 93 params.setAppLabel(remoteParams.getAppLabel()); 94 params.setTimeout(remoteParams.getTimeout()); 95 params.setLocale(remoteParams.getLocale()); 96 if (remoteParams.isForceNoDecor()) { 97 params.setForceNoDecor(); 98 } 99 params.setRtlSupport(remoteParams.isRtlSupported()); 100 if (remoteParams.isBgColorOverridden()) { 101 params.setOverrideBgColor(remoteParams.getOverrideBgColor()); 102 } 103 params.setImageFactory(remoteParams.getImageFactory()); 104 // TODO: Also unpack remote flags and pass them to RenderParams 105 } 106 107 @NotNull 108 @Override 109 public RemoteRenderSession createSession(@NotNull RemoteSessionParams remoteParams) { 110 try { 111 String projectKey = mCachedProjectKeys.putIfAbsent(remoteParams.getProjectKey(), 112 remoteParams.getProjectKey()); 113 114 // Unpack the remote params and convert it into the local SessionParams 115 SessionParams params = new SessionParams( 116 new RemoteILayoutPullParserAdapter(remoteParams.getLayoutDescription()), 117 remoteParams.getRenderingMode(), projectKey, 118 remoteParams.getRemoteHardwareConfig().getHardwareConfig(), 119 new RemoteRenderResourcesAdapter(remoteParams.getRemoteResources()), 120 new RemoteLayoutlibCallbackAdapter(remoteParams.getRemoteLayoutlibCallback()), 121 remoteParams.getMinSdkVersion(), remoteParams.getTargetSdkVersion(), 122 new RemoteLayoutLogAdapter(remoteParams.getLog())); 123 setupRenderParams(params, remoteParams); 124 return RemoteRenderSessionAdapter.create(mBridge.createSession(params)); 125 126 } catch (RemoteException e) { 127 throw new RuntimeException(e); 128 } 129 } 130 131 @NotNull 132 @Override 133 public Result renderDrawable(@NotNull RemoteDrawableParams remoteParams) { 134 try { 135 String projectKey = mCachedProjectKeys.putIfAbsent(remoteParams.getProjectKey(), 136 remoteParams.getProjectKey()); 137 138 DrawableParams params = new DrawableParams( 139 remoteParams.getDrawable(), 140 projectKey, 141 remoteParams.getRemoteHardwareConfig().getHardwareConfig(), 142 new RemoteRenderResourcesAdapter(remoteParams.getRemoteResources()), 143 new RemoteLayoutlibCallbackAdapter(remoteParams.getRemoteLayoutlibCallback()), 144 remoteParams.getMinSdkVersion(), remoteParams.getTargetSdkVersion(), 145 new RemoteLayoutLogAdapter(remoteParams.getLog())); 146 setupRenderParams(params, remoteParams); 147 return mBridge.renderDrawable(params); 148 } catch (RemoteException e) { 149 throw new RuntimeException(e); 150 } 151 } 152 153 @Override 154 public void clearCaches(String projectKey) { 155 mCachedProjectKeys.remove(projectKey); 156 mBridge.clearCaches(projectKey); 157 } 158 159 @Override 160 public boolean isRtl(String locale) { 161 return mBridge.isRtl(locale); 162 } 163} 164