From b3c9a9e907e469282e9fdeba97d8ab49289e4c30 Mon Sep 17 00:00:00 2001 From: shifujun Date: Thu, 26 Aug 2021 10:59:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81NativeActivity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 添加NativePluginContainerActivity 2. add ShadowNativeActivity 3. override getPackageManager返回插件ActivityInfo --- .../code_generator/ActivityCodeGenerator.kt | 46 +- .../container/HostNativeActivityDelegate.java | 42 ++ .../HostNativeActivityDelegator.java | 38 ++ .../NativePluginContainerActivity.java | 285 ++++++++ .../shadow/core/loader/ShadowPluginLoader.kt | 11 +- .../delegates/PackageManagerWrapper.java | 623 ++++++++++++++++++ .../delegates/ShadowActivityDelegate.kt | 7 +- .../delegates/ShadowNativeActivityDelegate.kt | 54 ++ .../core/runtime/ShadowNativeActivity.java | 55 ++ .../transform/specific/ActivityTransform.kt | 4 +- 10 files changed, 1141 insertions(+), 24 deletions(-) create mode 100644 projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/HostNativeActivityDelegate.java create mode 100644 projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/HostNativeActivityDelegator.java create mode 100644 projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/NativePluginContainerActivity.java create mode 100644 projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/PackageManagerWrapper.java create mode 100644 projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/ShadowNativeActivityDelegate.kt create mode 100644 projects/sdk/core/runtime/src/main/java/com/tencent/shadow/core/runtime/ShadowNativeActivity.java diff --git a/projects/sdk/coding/code-generator/src/main/kotlin/com/tencent/shadow/coding/code_generator/ActivityCodeGenerator.kt b/projects/sdk/coding/code-generator/src/main/kotlin/com/tencent/shadow/coding/code_generator/ActivityCodeGenerator.kt index 7c8289ed0..f8dc792ec 100644 --- a/projects/sdk/coding/code-generator/src/main/kotlin/com/tencent/shadow/coding/code_generator/ActivityCodeGenerator.kt +++ b/projects/sdk/coding/code-generator/src/main/kotlin/com/tencent/shadow/coding/code_generator/ActivityCodeGenerator.kt @@ -5,6 +5,7 @@ package com.tencent.shadow.coding.code_generator import android.annotation.SuppressLint import android.app.Activity import android.app.Application +import android.app.NativeActivity import android.view.ContextThemeWrapper import android.view.KeyEvent import android.view.Window @@ -15,6 +16,7 @@ import javassist.LoaderClassPath import javassist.bytecode.Descriptor import java.io.File import java.lang.reflect.Method +import java.lang.reflect.Type import javax.lang.model.element.Modifier /** @@ -62,6 +64,7 @@ class ActivityCodeGenerator { const val CS_HostActivityDelegate = "${PREFIX}HostActivityDelegate" const val CS_HostActivityDelegator = "${PREFIX}HostActivityDelegator" const val CS_PluginContainerActivity = "${PREFIX}PluginContainerActivity" + const val CS_NativePluginContainerActivity = "${PREFIX}NativePluginContainerActivity" const val CS_PluginActivity = "${PREFIX}PluginActivity" const val CS_ShadowActivityDelegate = "${PREFIX}ShadowActivityDelegate" const val CS_delegate_field = "hostActivityDelegate" @@ -80,6 +83,7 @@ class ActivityCodeGenerator { } val ActivityClass = Activity::class.java + val NativeActivityClass = NativeActivity::class.java val ModifiedActivityClass = modifySdkClass(Activity::class.java) val activityCallbackMethods = getActivityCallbackMethods(ActivityClass) val otherMethods = getOtherMethods(ActivityClass) @@ -328,7 +332,14 @@ class ActivityCodeGenerator { val activityDelegate = defineActivityDelegate() val activityDelegator = defineActivityDelegator() - val pluginContainerActivity = definePluginContainerActivity() + val pluginContainerActivity = definePluginContainerActivity( + CS_PluginContainerActivity, + ActivityClass + ) + val nativePluginContainerActivity = definePluginContainerActivity( + CS_NativePluginContainerActivity, + NativeActivityClass + ) val pluginActivity = definePluginActivity() val shadowActivityDelegate = defineShadowActivityDelegate() @@ -348,10 +359,10 @@ class ActivityCodeGenerator { + "以便Delegate可以通过这个接口调用到Activity的super方法。\n" ) - fun definePluginContainerActivity() = - TypeSpec.classBuilder(CS_PluginContainerActivity) + fun definePluginContainerActivity(className: String, superclass: Type) = + TypeSpec.classBuilder(className) .addModifiers(Modifier.ABSTRACT) - .superclass(ActivityClass) + .superclass(superclass) .addSuperinterface(ClassName.get(ACTIVITY_CONTAINER_PACKAGE, CS_HostActivityDelegator)) .addAnnotation( AnnotationSpec.builder(SuppressLint::class.java) @@ -425,6 +436,8 @@ class ActivityCodeGenerator { .build().writeTo(activityContainerOutput) JavaFile.builder(ACTIVITY_CONTAINER_PACKAGE, pluginContainerActivity.build()) .build().writeTo(activityContainerOutput) + JavaFile.builder(ACTIVITY_CONTAINER_PACKAGE, nativePluginContainerActivity.build()) + .build().writeTo(activityContainerOutput) JavaFile.builder(RUNTIME_PACKAGE, pluginActivity.build()) .build().writeTo(runtimeOutput) JavaFile.builder(DELEGATE_PACKAGE, shadowActivityDelegate.build()) @@ -459,25 +472,26 @@ class ActivityCodeGenerator { ) //对系统会调用的方法转调到hostActivityDelegate去,再生成对应的super方法 - pluginContainerActivity.addMethods( + listOf(pluginContainerActivity, nativePluginContainerActivity).forEach { + it.addMethods( activityCallbackMethods.map(::delegateCallbackMethod) - ) - pluginContainerActivity.addMethods( + ) + it.addMethods( activityCallbackMethods.map(::implementSuperMethod) - ) - - //TODO:这些方法并不需要添加super前缀方法,但先对齐原手工实现的类,保证单元测试检测生成类和原手工写的类一致可以通过。 - pluginContainerActivity.addMethods( + ) + //TODO:这些方法并不需要添加super前缀方法,但先对齐原手工实现的类,保证单元测试检测生成类和原手工写的类一致可以通过。 + it.addMethods( otherMethods.filterNot { activityCallbackMethods.contains(it) } - .map(::implementSuperMethod) - ) + .map(::implementSuperMethod) + ) - //将所有protected方法暴露成public方法 - pluginContainerActivity.addMethods( + //将所有protected方法暴露成public方法 + it.addMethods( otherMethods.filter { java.lang.reflect.Modifier.isProtected(it.modifiers) }.map(::exposeProtectedMethod) - ) + ) + } pluginActivity.addMethods( activityCallbackMethodsModified diff --git a/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/HostNativeActivityDelegate.java b/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/HostNativeActivityDelegate.java new file mode 100644 index 000000000..812d04db5 --- /dev/null +++ b/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/HostNativeActivityDelegate.java @@ -0,0 +1,42 @@ +/* + * Tencent is pleased to support the open source community by making Tencent Shadow available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.tencent.shadow.core.runtime.container; + +import android.content.pm.PackageManager; +import android.view.InputQueue; +import android.view.SurfaceHolder; + +public interface HostNativeActivityDelegate extends HostActivityDelegate { + + PackageManager getPackageManager(); + + void surfaceCreated(SurfaceHolder holder); + + void surfaceChanged(SurfaceHolder holder, int format, int width, int height); + + void surfaceRedrawNeeded(SurfaceHolder holder); + + void surfaceDestroyed(SurfaceHolder holder); + + void onInputQueueCreated(InputQueue queue); + + void onInputQueueDestroyed(InputQueue queue); + + void onGlobalLayout(); +} diff --git a/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/HostNativeActivityDelegator.java b/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/HostNativeActivityDelegator.java new file mode 100644 index 000000000..8f6dc9d2c --- /dev/null +++ b/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/HostNativeActivityDelegator.java @@ -0,0 +1,38 @@ +/* + * Tencent is pleased to support the open source community by making Tencent Shadow available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.tencent.shadow.core.runtime.container; + +import android.view.InputQueue; +import android.view.SurfaceHolder; + +public interface HostNativeActivityDelegator extends HostActivityDelegator { + void superSurfaceCreated(SurfaceHolder holder); + + void superSurfaceChanged(SurfaceHolder holder, int format, int width, int height); + + void superSurfaceRedrawNeeded(SurfaceHolder holder); + + void superSurfaceDestroyed(SurfaceHolder holder); + + void superOnInputQueueCreated(InputQueue queue); + + void superOnInputQueueDestroyed(InputQueue queue); + + void superOnGlobalLayout(); +} diff --git a/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/NativePluginContainerActivity.java b/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/NativePluginContainerActivity.java new file mode 100644 index 000000000..0000ae1f1 --- /dev/null +++ b/projects/sdk/core/activity-container/src/main/java/com/tencent/shadow/core/runtime/container/NativePluginContainerActivity.java @@ -0,0 +1,285 @@ +/* + * Tencent is pleased to support the open source community by making Tencent Shadow available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.tencent.shadow.core.runtime.container; + +import static com.tencent.shadow.core.runtime.container.DelegateProvider.LOADER_VERSION_KEY; +import static com.tencent.shadow.core.runtime.container.DelegateProvider.PROCESS_ID_KEY; + +import android.app.Activity; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.os.Bundle; +import android.util.Log; +import android.view.InputQueue; +import android.view.SurfaceHolder; +import android.view.Window; + +import com.tencent.shadow.core.container.BuildConfig; + +/** + * NativeActivity位于宿主中的壳子 + *

+ * TODO 和PluginContainerActivity重复代码过多,但由于是继承自不同父类,需要用JavaPoet生成代码来减少重复。 + */ +public class NativePluginContainerActivity extends GeneratedNativePluginContainerActivity implements HostActivity, HostNativeActivityDelegator { + private static final String TAG = "NativePluginConAct"; + + HostNativeActivityDelegate hostActivityDelegate; + + private boolean isBeforeOnCreate = true; + + public NativePluginContainerActivity() { + HostNativeActivityDelegate delegate; + DelegateProvider delegateProvider = DelegateProviderHolder.getDelegateProvider(getDelegateProviderKey()); + if (delegateProvider != null) { + delegate = (HostNativeActivityDelegate) delegateProvider.getHostActivityDelegate(this.getClass()); + delegate.setDelegator(this); + } else { + Log.e(TAG, "NativePluginContainerActivity: DelegateProviderHolder没有初始化"); + delegate = null; + } + super.hostActivityDelegate = delegate; + hostActivityDelegate = delegate; + } + + protected String getDelegateProviderKey() { + return DelegateProviderHolder.DEFAULT_KEY; + } + + final public Object getPluginActivity() { + if (hostActivityDelegate != null) { + return hostActivityDelegate.getPluginActivity(); + } else { + return null; + } + } + + @Override + final protected void onCreate(Bundle savedInstanceState) { + isBeforeOnCreate = false; + mHostTheme = null;//释放资源 + + boolean illegalIntent = isIllegalIntent(savedInstanceState); + if (illegalIntent) { + super.hostActivityDelegate = null; + hostActivityDelegate = null; + Log.e(TAG, "illegalIntent savedInstanceState==" + savedInstanceState + " getIntent().getExtras()==" + getIntent().getExtras()); + } + + if (hostActivityDelegate != null) { + hostActivityDelegate.onCreate(savedInstanceState); + } else { + //这里是进程被杀后重启后走到,当需要恢复fragment状态的时候,由于系统保留了TAG,会因为找不到fragment引起crash + super.onCreate(null); + Log.e(TAG, "onCreate: hostActivityDelegate==null finish activity"); + finish(); + System.exit(0); + } + } + + /** + * IllegalIntent指的是这些情况下的启动: + * 1.插件版本变化之后,残留于系统中的PendingIntent或系统因回收内存杀死进程残留的任务栈而启动。 + * 由于插件版本变化,PluginLoader逻辑可能不一致,Intent中的参数可能不能满足新代码的启动条件。 + * 2.外部的非法启动,无法确定一个插件的Activity。 + *

+ *

+ * 3.不支持进程重启后莫名其妙的原因loader也加载了,但是可能要启动的plugin没有load,出现异常 + * + * @param savedInstanceState onCreate时系统还回来的savedInstanceState + * @return true表示这次启动不是我们预料的,需要尽早finish并退出进程。 + */ + private boolean isIllegalIntent(Bundle savedInstanceState) { + Bundle extras = getIntent().getExtras(); + if (extras == null && savedInstanceState == null) { + return true; + } + Bundle bundle; + bundle = savedInstanceState == null ? extras : savedInstanceState; + try { + String loaderVersion = bundle.getString(LOADER_VERSION_KEY); + long processVersion = bundle.getLong(PROCESS_ID_KEY); + return !BuildConfig.VERSION_NAME.equals(loaderVersion) || processVersion != DelegateProviderHolder.sCustomPid; + } catch (Throwable ignored) { + //捕获可能的非法Intent中包含我们根本反序列化不了的数据 + return true; + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + if (hostActivityDelegate != null) { + hostActivityDelegate.onSaveInstanceState(outState); + } else { + super.onSaveInstanceState(outState); + } + //避免插件setIntent清空掉LOADER_VERSION_KEY + outState.putString(LOADER_VERSION_KEY, BuildConfig.VERSION_NAME); + outState.putLong(PROCESS_ID_KEY, DelegateProviderHolder.sCustomPid); + } + + @Override + public HostActivity getHostActivity() { + return this; + } + + @Override + public Activity getImplementActivity() { + return this; + } + + @Override + public Window getImplementWindow() { + return getWindow(); + } + + /** + * Theme一旦设置了就不能更换Theme所在的Resouces了,见{@link Resources.Theme#setTo(Resources.Theme)} + * 而Activity在OnCreate之前需要设置Theme和使用Theme。我们需要在Activity OnCreate之后才能注入插件资源。 + * 这就需要在Activity OnCreate之前不要调用Activity的setTheme方法,同时在getTheme时返回宿主的Theme资源。 + * 注:{@link Activity#setTheme(int)}会触发初始化Theme,因此不能调用。 + */ + private Resources.Theme mHostTheme; + + @Override + public Resources.Theme getTheme() { + if (isBeforeOnCreate) { + if (mHostTheme == null) { + mHostTheme = super.getResources().newTheme(); + } + return mHostTheme; + } else { + return super.getTheme(); + } + } + + @Override + public void setTheme(int resid) { + if (!isBeforeOnCreate) { + super.setTheme(resid); + } + } + + @Override + public PackageManager getPackageManager() { + if (hostActivityDelegate != null) { + return hostActivityDelegate.getPackageManager(); + } else { + return super.getPackageManager(); + } + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + if (hostActivityDelegate != null) { + hostActivityDelegate.surfaceCreated(holder); + } else { + super.surfaceCreated(holder); + } + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + if (hostActivityDelegate != null) { + hostActivityDelegate.surfaceChanged(holder, format, width, height); + } else { + super.surfaceChanged(holder, format, width, height); + } + } + + @Override + public void surfaceRedrawNeeded(SurfaceHolder holder) { + if (hostActivityDelegate != null) { + hostActivityDelegate.surfaceRedrawNeeded(holder); + } else { + super.surfaceRedrawNeeded(holder); + } + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + if (hostActivityDelegate != null) { + hostActivityDelegate.surfaceDestroyed(holder); + } else { + super.surfaceDestroyed(holder); + } + } + + @Override + public void onInputQueueCreated(InputQueue queue) { + if (hostActivityDelegate != null) { + hostActivityDelegate.onInputQueueCreated(queue); + } else { + super.onInputQueueCreated(queue); + } + } + + @Override + public void onInputQueueDestroyed(InputQueue queue) { + if (hostActivityDelegate != null) { + hostActivityDelegate.onInputQueueDestroyed(queue); + } else { + super.onInputQueueDestroyed(queue); + } + } + + @Override + public void onGlobalLayout() { + if (hostActivityDelegate != null) { + hostActivityDelegate.onGlobalLayout(); + } else { + super.onGlobalLayout(); + } + } + + @Override + public void superSurfaceCreated(SurfaceHolder holder) { + super.surfaceCreated(holder); + } + + @Override + public void superSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { + super.surfaceChanged(holder, format, width, height); + } + + @Override + public void superSurfaceRedrawNeeded(SurfaceHolder holder) { + super.surfaceRedrawNeeded(holder); + } + + @Override + public void superSurfaceDestroyed(SurfaceHolder holder) { + super.surfaceDestroyed(holder); + } + + @Override + public void superOnInputQueueCreated(InputQueue queue) { + super.onInputQueueCreated(queue); + } + + @Override + public void superOnInputQueueDestroyed(InputQueue queue) { + super.onInputQueueDestroyed(queue); + } + + @Override + public void superOnGlobalLayout() { + super.onGlobalLayout(); + } +} diff --git a/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/ShadowPluginLoader.kt b/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/ShadowPluginLoader.kt index e41de6d95..3bc68bde4 100644 --- a/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/ShadowPluginLoader.kt +++ b/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/ShadowPluginLoader.kt @@ -27,10 +27,7 @@ import com.tencent.shadow.core.common.InstalledApk import com.tencent.shadow.core.common.LoggerFactory import com.tencent.shadow.core.load_parameters.LoadParameters import com.tencent.shadow.core.loader.blocs.LoadPluginBloc -import com.tencent.shadow.core.loader.delegates.DI -import com.tencent.shadow.core.loader.delegates.ShadowActivityDelegate -import com.tencent.shadow.core.loader.delegates.ShadowContentProviderDelegate -import com.tencent.shadow.core.loader.delegates.ShadowDelegate +import com.tencent.shadow.core.loader.delegates.* import com.tencent.shadow.core.loader.exceptions.LoadPluginException import com.tencent.shadow.core.loader.infos.PluginParts import com.tencent.shadow.core.loader.managers.ComponentManager @@ -178,7 +175,11 @@ abstract class ShadowPluginLoader(hostAppContext: Context) : DelegateProvider, D } override fun getHostActivityDelegate(aClass: Class): HostActivityDelegate { - return ShadowActivityDelegate(this) + return if (HostNativeActivityDelegator::class.java.isAssignableFrom(aClass)) { + ShadowNativeActivityDelegate(this) + } else { + ShadowActivityDelegate(this) + } } diff --git a/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/PackageManagerWrapper.java b/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/PackageManagerWrapper.java new file mode 100644 index 000000000..dae0563ec --- /dev/null +++ b/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/PackageManagerWrapper.java @@ -0,0 +1,623 @@ +package com.tencent.shadow.core.loader.delegates; + +import android.annotation.SuppressLint; +import android.content.ComponentName; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ChangedPackages; +import android.content.pm.FeatureInfo; +import android.content.pm.InstallSourceInfo; +import android.content.pm.InstrumentationInfo; +import android.content.pm.ModuleInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageManager; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.pm.SharedLibraryInfo; +import android.content.pm.VersionedPackage; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.UserHandle; + +import java.util.List; +import java.util.Set; + +@SuppressLint("NewApi") +class PackageManagerWrapper extends PackageManager { + final private PackageManager proxy; + + PackageManagerWrapper(PackageManager proxy) { + this.proxy = proxy; + } + + @Override + public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { + return proxy.getPackageInfo(packageName, flags); + } + + @Override + public PackageInfo getPackageInfo(VersionedPackage versionedPackage, int flags) throws NameNotFoundException { + return proxy.getPackageInfo(versionedPackage, flags); + } + + @Override + public String[] currentToCanonicalPackageNames(String[] packageNames) { + return proxy.currentToCanonicalPackageNames(packageNames); + } + + @Override + public String[] canonicalToCurrentPackageNames(String[] packageNames) { + return proxy.canonicalToCurrentPackageNames(packageNames); + } + + @Override + public Intent getLaunchIntentForPackage(String packageName) { + return proxy.getLaunchIntentForPackage(packageName); + } + + @Override + public Intent getLeanbackLaunchIntentForPackage(String packageName) { + return proxy.getLeanbackLaunchIntentForPackage(packageName); + } + + @Override + public int[] getPackageGids(String packageName) throws NameNotFoundException { + return proxy.getPackageGids(packageName); + } + + @Override + public int[] getPackageGids(String packageName, int flags) throws NameNotFoundException { + return proxy.getPackageGids(packageName, flags); + } + + @Override + public int getPackageUid(String packageName, int flags) throws NameNotFoundException { + return proxy.getPackageUid(packageName, flags); + } + + @Override + public PermissionInfo getPermissionInfo(String permName, int flags) throws NameNotFoundException { + return proxy.getPermissionInfo(permName, flags); + } + + @Override + public List queryPermissionsByGroup(String permissionGroup, int flags) throws NameNotFoundException { + return proxy.queryPermissionsByGroup(permissionGroup, flags); + } + + @Override + public PermissionGroupInfo getPermissionGroupInfo(String permName, int flags) throws NameNotFoundException { + return proxy.getPermissionGroupInfo(permName, flags); + } + + @Override + public List getAllPermissionGroups(int flags) { + return proxy.getAllPermissionGroups(flags); + } + + @Override + public ApplicationInfo getApplicationInfo(String packageName, int flags) throws NameNotFoundException { + return proxy.getApplicationInfo(packageName, flags); + } + + @Override + public ActivityInfo getActivityInfo(ComponentName component, int flags) throws NameNotFoundException { + return proxy.getActivityInfo(component, flags); + } + + @Override + public ActivityInfo getReceiverInfo(ComponentName component, int flags) throws NameNotFoundException { + return proxy.getReceiverInfo(component, flags); + } + + @Override + public ServiceInfo getServiceInfo(ComponentName component, int flags) throws NameNotFoundException { + return proxy.getServiceInfo(component, flags); + } + + @Override + public ProviderInfo getProviderInfo(ComponentName component, int flags) throws NameNotFoundException { + return proxy.getProviderInfo(component, flags); + } + + @Override + public ModuleInfo getModuleInfo(String packageName, int flags) throws NameNotFoundException { + return proxy.getModuleInfo(packageName, flags); + } + + @Override + public List getInstalledModules(int flags) { + return proxy.getInstalledModules(flags); + } + + @Override + public List getInstalledPackages(int flags) { + return proxy.getInstalledPackages(flags); + } + + @Override + public List getPackagesHoldingPermissions(String[] permissions, int flags) { + return proxy.getPackagesHoldingPermissions(permissions, flags); + } + + @Override + public int checkPermission(String permName, String packageName) { + return proxy.checkPermission(permName, packageName); + } + + @Override + public boolean isPermissionRevokedByPolicy(String permName, String packageName) { + return proxy.isPermissionRevokedByPolicy(permName, packageName); + } + + @Override + public boolean addPermission(PermissionInfo info) { + return proxy.addPermission(info); + } + + @Override + public boolean addPermissionAsync(PermissionInfo info) { + return proxy.addPermissionAsync(info); + } + + @Override + public void removePermission(String permName) { + proxy.removePermission(permName); + } + + @Override + public Set getWhitelistedRestrictedPermissions(String packageName, int whitelistFlag) { + return proxy.getWhitelistedRestrictedPermissions(packageName, whitelistFlag); + } + + @Override + public boolean addWhitelistedRestrictedPermission(String packageName, String permName, int whitelistFlags) { + return proxy.addWhitelistedRestrictedPermission(packageName, permName, whitelistFlags); + } + + @Override + public boolean removeWhitelistedRestrictedPermission(String packageName, String permName, int whitelistFlags) { + return proxy.removeWhitelistedRestrictedPermission(packageName, permName, whitelistFlags); + } + + @Override + public boolean setAutoRevokeWhitelisted(String packageName, boolean whitelisted) { + return proxy.setAutoRevokeWhitelisted(packageName, whitelisted); + } + + @Override + public boolean isAutoRevokeWhitelisted(String packageName) { + return proxy.isAutoRevokeWhitelisted(packageName); + } + + @Override + public CharSequence getBackgroundPermissionOptionLabel() { + return proxy.getBackgroundPermissionOptionLabel(); + } + + @Override + public int checkSignatures(String packageName1, String packageName2) { + return proxy.checkSignatures(packageName1, packageName2); + } + + @Override + public int checkSignatures(int uid1, int uid2) { + return proxy.checkSignatures(uid1, uid2); + } + + @Override + public String[] getPackagesForUid(int uid) { + return proxy.getPackagesForUid(uid); + } + + @Override + public String getNameForUid(int uid) { + return proxy.getNameForUid(uid); + } + + @Override + public List getInstalledApplications(int flags) { + return proxy.getInstalledApplications(flags); + } + + @Override + public boolean isInstantApp() { + return proxy.isInstantApp(); + } + + @Override + public boolean isInstantApp(String packageName) { + return proxy.isInstantApp(packageName); + } + + @Override + public int getInstantAppCookieMaxBytes() { + return proxy.getInstantAppCookieMaxBytes(); + } + + @Override + public byte[] getInstantAppCookie() { + return proxy.getInstantAppCookie(); + } + + @Override + public void clearInstantAppCookie() { + proxy.clearInstantAppCookie(); + } + + @Override + public void updateInstantAppCookie(byte[] cookie) { + proxy.updateInstantAppCookie(cookie); + } + + @Override + public String[] getSystemSharedLibraryNames() { + return proxy.getSystemSharedLibraryNames(); + } + + @Override + public List getSharedLibraries(int flags) { + return proxy.getSharedLibraries(flags); + } + + @Override + public ChangedPackages getChangedPackages(int sequenceNumber) { + return proxy.getChangedPackages(sequenceNumber); + } + + @Override + public FeatureInfo[] getSystemAvailableFeatures() { + return proxy.getSystemAvailableFeatures(); + } + + @Override + public boolean hasSystemFeature(String featureName) { + return proxy.hasSystemFeature(featureName); + } + + @Override + public boolean hasSystemFeature(String featureName, int version) { + return proxy.hasSystemFeature(featureName, version); + } + + @Override + public ResolveInfo resolveActivity(Intent intent, int flags) { + return proxy.resolveActivity(intent, flags); + } + + @Override + public List queryIntentActivities(Intent intent, int flags) { + return proxy.queryIntentActivities(intent, flags); + } + + @Override + public List queryIntentActivityOptions(ComponentName caller, Intent[] specifics, Intent intent, int flags) { + return proxy.queryIntentActivityOptions(caller, specifics, intent, flags); + } + + @Override + public List queryBroadcastReceivers(Intent intent, int flags) { + return proxy.queryBroadcastReceivers(intent, flags); + } + + @Override + public ResolveInfo resolveService(Intent intent, int flags) { + return proxy.resolveService(intent, flags); + } + + @Override + public List queryIntentServices(Intent intent, int flags) { + return proxy.queryIntentServices(intent, flags); + } + + @Override + public List queryIntentContentProviders(Intent intent, int flags) { + return proxy.queryIntentContentProviders(intent, flags); + } + + @Override + public ProviderInfo resolveContentProvider(String authority, int flags) { + return proxy.resolveContentProvider(authority, flags); + } + + @Override + public List queryContentProviders(String processName, int uid, int flags) { + return proxy.queryContentProviders(processName, uid, flags); + } + + @Override + public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags) throws NameNotFoundException { + return proxy.getInstrumentationInfo(className, flags); + } + + @Override + public List queryInstrumentation(String targetPackage, int flags) { + return proxy.queryInstrumentation(targetPackage, flags); + } + + @Override + public Drawable getDrawable(String packageName, int resid, ApplicationInfo appInfo) { + return proxy.getDrawable(packageName, resid, appInfo); + } + + @Override + public Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException { + return proxy.getActivityIcon(activityName); + } + + @Override + public Drawable getActivityIcon(Intent intent) throws NameNotFoundException { + return proxy.getActivityIcon(intent); + } + + @Override + public Drawable getActivityBanner(ComponentName activityName) throws NameNotFoundException { + return proxy.getActivityBanner(activityName); + } + + @Override + public Drawable getActivityBanner(Intent intent) throws NameNotFoundException { + return proxy.getActivityBanner(intent); + } + + @Override + public Drawable getDefaultActivityIcon() { + return proxy.getDefaultActivityIcon(); + } + + @Override + public Drawable getApplicationIcon(ApplicationInfo info) { + return proxy.getApplicationIcon(info); + } + + @Override + public Drawable getApplicationIcon(String packageName) throws NameNotFoundException { + return proxy.getApplicationIcon(packageName); + } + + @Override + public Drawable getApplicationBanner(ApplicationInfo info) { + return proxy.getApplicationBanner(info); + } + + @Override + public Drawable getApplicationBanner(String packageName) throws NameNotFoundException { + return proxy.getApplicationBanner(packageName); + } + + @Override + public Drawable getActivityLogo(ComponentName activityName) throws NameNotFoundException { + return proxy.getActivityLogo(activityName); + } + + @Override + public Drawable getActivityLogo(Intent intent) throws NameNotFoundException { + return proxy.getActivityLogo(intent); + } + + @Override + public Drawable getApplicationLogo(ApplicationInfo info) { + return proxy.getApplicationLogo(info); + } + + @Override + public Drawable getApplicationLogo(String packageName) throws NameNotFoundException { + return proxy.getApplicationLogo(packageName); + } + + @Override + public Drawable getUserBadgedIcon(Drawable drawable, UserHandle user) { + return proxy.getUserBadgedIcon(drawable, user); + } + + @Override + public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user, Rect badgeLocation, int badgeDensity) { + return proxy.getUserBadgedDrawableForDensity(drawable, user, badgeLocation, badgeDensity); + } + + @Override + public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) { + return proxy.getUserBadgedLabel(label, user); + } + + @Override + public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) { + return proxy.getText(packageName, resid, appInfo); + } + + @Override + public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) { + return proxy.getXml(packageName, resid, appInfo); + } + + @Override + public CharSequence getApplicationLabel(ApplicationInfo info) { + return proxy.getApplicationLabel(info); + } + + @Override + public Resources getResourcesForActivity(ComponentName activityName) throws NameNotFoundException { + return proxy.getResourcesForActivity(activityName); + } + + @Override + public Resources getResourcesForApplication(ApplicationInfo app) throws NameNotFoundException { + return proxy.getResourcesForApplication(app); + } + + @Override + public Resources getResourcesForApplication(String packageName) throws NameNotFoundException { + return proxy.getResourcesForApplication(packageName); + } + + @Override + public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) { + return proxy.getPackageArchiveInfo(archiveFilePath, flags); + } + + @Override + public void verifyPendingInstall(int id, int verificationCode) { + proxy.verifyPendingInstall(id, verificationCode); + } + + @Override + public void extendVerificationTimeout(int id, int verificationCodeAtTimeout, long millisecondsToDelay) { + proxy.extendVerificationTimeout(id, verificationCodeAtTimeout, millisecondsToDelay); + } + + @Override + public void setInstallerPackageName(String targetPackage, String installerPackageName) { + proxy.setInstallerPackageName(targetPackage, installerPackageName); + } + + @Override + @Deprecated + public String getInstallerPackageName(String packageName) { + return proxy.getInstallerPackageName(packageName); + } + + @Override + public InstallSourceInfo getInstallSourceInfo(String packageName) throws NameNotFoundException { + return proxy.getInstallSourceInfo(packageName); + } + + @Override + @Deprecated + public void addPackageToPreferred(String packageName) { + proxy.addPackageToPreferred(packageName); + } + + @Override + @Deprecated + public void removePackageFromPreferred(String packageName) { + proxy.removePackageFromPreferred(packageName); + } + + @Override + @Deprecated + public List getPreferredPackages(int flags) { + return proxy.getPreferredPackages(flags); + } + + @Override + @Deprecated + public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { + proxy.addPreferredActivity(filter, match, set, activity); + } + + @Override + @Deprecated + public void clearPackagePreferredActivities(String packageName) { + proxy.clearPackagePreferredActivities(packageName); + } + + @Override + @Deprecated + public int getPreferredActivities(List outFilters, List outActivities, String packageName) { + return proxy.getPreferredActivities(outFilters, outActivities, packageName); + } + + @Override + public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) { + proxy.setComponentEnabledSetting(componentName, newState, flags); + } + + @Override + public int getComponentEnabledSetting(ComponentName componentName) { + return proxy.getComponentEnabledSetting(componentName); + } + + @Override + public boolean getSyntheticAppDetailsActivityEnabled(String packageName) { + return proxy.getSyntheticAppDetailsActivityEnabled(packageName); + } + + @Override + public void setApplicationEnabledSetting(String packageName, int newState, int flags) { + proxy.setApplicationEnabledSetting(packageName, newState, flags); + } + + @Override + public int getApplicationEnabledSetting(String packageName) { + return proxy.getApplicationEnabledSetting(packageName); + } + + @Override + public boolean isSafeMode() { + return proxy.isSafeMode(); + } + + @Override + public boolean isPackageSuspended(String packageName) throws NameNotFoundException { + return proxy.isPackageSuspended(packageName); + } + + @Override + public boolean isPackageSuspended() { + return proxy.isPackageSuspended(); + } + + @Override + public Bundle getSuspendedPackageAppExtras() { + return proxy.getSuspendedPackageAppExtras(); + } + + @Override + public void setApplicationCategoryHint(String packageName, int categoryHint) { + proxy.setApplicationCategoryHint(packageName, categoryHint); + } + + @Override + public boolean isDeviceUpgrading() { + return proxy.isDeviceUpgrading(); + } + + @Override + public PackageInstaller getPackageInstaller() { + return proxy.getPackageInstaller(); + } + + @Override + public boolean canRequestPackageInstalls() { + return proxy.canRequestPackageInstalls(); + } + + @Override + public boolean hasSigningCertificate(String packageName, byte[] certificate, int type) { + return proxy.hasSigningCertificate(packageName, certificate, type); + } + + @Override + public boolean hasSigningCertificate(int uid, byte[] certificate, int type) { + return proxy.hasSigningCertificate(uid, certificate, type); + } + + @Override + public boolean isAutoRevokeWhitelisted() { + return proxy.isAutoRevokeWhitelisted(); + } + + @Override + public boolean isDefaultApplicationIcon(Drawable drawable) { + return proxy.isDefaultApplicationIcon(drawable); + } + + @Override + public void setMimeGroup(String mimeGroup, Set mimeTypes) { + proxy.setMimeGroup(mimeGroup, mimeTypes); + } + + @Override + public Set getMimeGroup(String mimeGroup) { + return proxy.getMimeGroup(mimeGroup); + } +} diff --git a/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/ShadowActivityDelegate.kt b/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/ShadowActivityDelegate.kt index d5e07e9c0..f1a86f2a2 100644 --- a/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/ShadowActivityDelegate.kt +++ b/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/ShadowActivityDelegate.kt @@ -50,13 +50,14 @@ import com.tencent.shadow.core.runtime.container.HostActivityDelegator * * @author cubershi */ -class ShadowActivityDelegate(private val mDI: DI) : GeneratedShadowActivityDelegate(), HostActivityDelegate { +open class ShadowActivityDelegate(private val mDI: DI) : GeneratedShadowActivityDelegate(), + HostActivityDelegate { companion object { const val PLUGIN_OUT_STATE_KEY = "PLUGIN_OUT_STATE_KEY" val mLogger = LoggerFactory.getLogger(ShadowActivityDelegate::class.java) } - private lateinit var mHostActivityDelegator: HostActivityDelegator + protected lateinit var mHostActivityDelegator: HostActivityDelegator private val mPluginActivity get() = super.pluginActivity private lateinit var mBusinessName: String private lateinit var mPartKey: String @@ -81,6 +82,7 @@ class ShadowActivityDelegate(private val mDI: DI) : GeneratedShadowActivityDeleg private lateinit var mCurrentConfiguration: Configuration private var mPluginHandleConfigurationChange: Int = 0 private var mCallingActivity: ComponentName? = null + protected lateinit var mPluginActivityInfo: PluginActivityInfo override fun onCreate(savedInstanceState: Bundle?) { val pluginInitBundle = savedInstanceState ?: mHostActivityDelegator.intent.extras!! @@ -99,6 +101,7 @@ class ShadowActivityDelegate(private val mDI: DI) : GeneratedShadowActivityDeleg bundleForPluginLoader.classLoader = this.javaClass.classLoader val pluginActivityClassName = bundleForPluginLoader.getString(CM_CLASS_NAME_KEY)!! val pluginActivityInfo: PluginActivityInfo = bundleForPluginLoader.getParcelable(CM_ACTIVITY_INFO_KEY)!! + mPluginActivityInfo = pluginActivityInfo mCurrentConfiguration = Configuration(resources.configuration) mPluginHandleConfigurationChange = diff --git a/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/ShadowNativeActivityDelegate.kt b/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/ShadowNativeActivityDelegate.kt new file mode 100644 index 000000000..1c75aaf1e --- /dev/null +++ b/projects/sdk/core/loader/src/main/kotlin/com/tencent/shadow/core/loader/delegates/ShadowNativeActivityDelegate.kt @@ -0,0 +1,54 @@ +package com.tencent.shadow.core.loader.delegates + +import android.content.ComponentName +import android.content.pm.ActivityInfo +import android.content.pm.PackageManager +import android.view.InputQueue +import android.view.SurfaceHolder +import com.tencent.shadow.core.runtime.ShadowNativeActivity +import com.tencent.shadow.core.runtime.container.HostNativeActivityDelegate + +class ShadowNativeActivityDelegate(mDI: DI) : ShadowActivityDelegate(mDI), + HostNativeActivityDelegate { + + private val mPluginActivity: ShadowNativeActivity + get() + = super.pluginActivity as ShadowNativeActivity + + override fun surfaceCreated(holder: SurfaceHolder) { + return mPluginActivity.surfaceCreated(holder) + } + + override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + return mPluginActivity.surfaceChanged(holder, format, width, height) + } + + override fun surfaceRedrawNeeded(holder: SurfaceHolder) { + return mPluginActivity.surfaceRedrawNeeded(holder) + } + + override fun surfaceDestroyed(holder: SurfaceHolder) { + return mPluginActivity.surfaceDestroyed(holder) + } + + override fun onInputQueueCreated(queue: InputQueue) { + return mPluginActivity.onInputQueueCreated(queue) + } + + override fun onInputQueueDestroyed(queue: InputQueue) { + return mPluginActivity.onInputQueueCreated(queue) + } + + override fun onGlobalLayout() { + return mPluginActivity.onGlobalLayout() + } + + //预期只有NativeActivity会调用这个方法 + override fun getPackageManager(): PackageManager { + return object : PackageManagerWrapper(mHostActivityDelegator.superGetPackageManager()) { + override fun getActivityInfo(component: ComponentName, flags: Int): ActivityInfo { + return mPluginActivityInfo.activityInfo!! + } + } + } +} diff --git a/projects/sdk/core/runtime/src/main/java/com/tencent/shadow/core/runtime/ShadowNativeActivity.java b/projects/sdk/core/runtime/src/main/java/com/tencent/shadow/core/runtime/ShadowNativeActivity.java new file mode 100644 index 000000000..241c8b07b --- /dev/null +++ b/projects/sdk/core/runtime/src/main/java/com/tencent/shadow/core/runtime/ShadowNativeActivity.java @@ -0,0 +1,55 @@ +package com.tencent.shadow.core.runtime; + +import android.view.InputQueue; +import android.view.SurfaceHolder; +import android.view.ViewTreeObserver; + +import com.tencent.shadow.core.runtime.container.HostActivityDelegator; +import com.tencent.shadow.core.runtime.container.HostNativeActivityDelegator; + +public class ShadowNativeActivity extends ShadowActivity implements SurfaceHolder.Callback2, + InputQueue.Callback, ViewTreeObserver.OnGlobalLayoutListener { + + private HostNativeActivityDelegator hostNativeActivityDelegator; + + @Override + public void setHostActivityDelegator(HostActivityDelegator delegator) { + super.setHostActivityDelegator(delegator); + hostNativeActivityDelegator = (HostNativeActivityDelegator) delegator; + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + hostNativeActivityDelegator.superSurfaceCreated(holder); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + hostNativeActivityDelegator.superSurfaceChanged(holder, format, width, height); + } + + @Override + public void surfaceRedrawNeeded(SurfaceHolder holder) { + hostNativeActivityDelegator.superSurfaceRedrawNeeded(holder); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + hostNativeActivityDelegator.superSurfaceDestroyed(holder); + } + + @Override + public void onInputQueueCreated(InputQueue queue) { + hostNativeActivityDelegator.superOnInputQueueCreated(queue); + } + + @Override + public void onInputQueueDestroyed(InputQueue queue) { + hostNativeActivityDelegator.superOnInputQueueDestroyed(queue); + } + + @Override + public void onGlobalLayout() { + hostNativeActivityDelegator.superOnGlobalLayout(); + } +} diff --git a/projects/sdk/core/transform/src/main/kotlin/com/tencent/shadow/core/transform/specific/ActivityTransform.kt b/projects/sdk/core/transform/src/main/kotlin/com/tencent/shadow/core/transform/specific/ActivityTransform.kt index 624a5e5b7..f5bea2934 100644 --- a/projects/sdk/core/transform/src/main/kotlin/com/tencent/shadow/core/transform/specific/ActivityTransform.kt +++ b/projects/sdk/core/transform/src/main/kotlin/com/tencent/shadow/core/transform/specific/ActivityTransform.kt @@ -21,6 +21,8 @@ package com.tencent.shadow.core.transform.specific class ActivityTransform : SimpleRenameTransform( mapOf( "android.app.Activity" - to "com.tencent.shadow.core.runtime.ShadowActivity" + to "com.tencent.shadow.core.runtime.ShadowActivity", + "android.app.NativeActivity" + to "com.tencent.shadow.core.runtime.ShadowNativeActivity" ) )