mirror of
https://gitee.com/replugin/RePlugin.git
synced 2024-12-02 03:38:06 +08:00
Resolved the issue of "Overwriting the plug-in, it may not be notified to other processes"
Also modified: * Added the "getParentInfo" method in the PluginInfo class * IsNewOrUpdatedPlugin removed from PmBase because it is no longer needed
This commit is contained in:
parent
1b346fbc1f
commit
4fb15f8c41
@ -32,7 +32,6 @@ import android.text.TextUtils;
|
||||
import com.qihoo360.i.Factory;
|
||||
import com.qihoo360.i.IModule;
|
||||
import com.qihoo360.i.IPluginManager;
|
||||
import com.qihoo360.replugin.utils.ReflectUtils;
|
||||
import com.qihoo360.mobilesafe.api.Tasks;
|
||||
import com.qihoo360.replugin.IHostBinderFetcher;
|
||||
import com.qihoo360.replugin.RePlugin;
|
||||
@ -49,6 +48,7 @@ import com.qihoo360.replugin.helper.LogDebug;
|
||||
import com.qihoo360.replugin.helper.LogRelease;
|
||||
import com.qihoo360.replugin.model.PluginInfo;
|
||||
import com.qihoo360.replugin.packages.PluginManagerProxy;
|
||||
import com.qihoo360.replugin.utils.ReflectUtils;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@ -997,20 +997,6 @@ class PmBase {
|
||||
return mPlugins.get(plugin);
|
||||
}
|
||||
|
||||
// 是否为新的,或已经更新过的插件
|
||||
// 注意:若“插件正在运行”时触发更新,则这里应返回false,这样外界将不会发送“新插件”广播
|
||||
final boolean isNewOrUpdatedPlugin(PluginInfo info) {
|
||||
Plugin p = mPlugins.get(info.getName());
|
||||
|
||||
// 满足三个条件的其一就表示为"新插件",可以做下一步处理
|
||||
// 1. p为空,表示为全新插件
|
||||
// 2. 要安装的版本比当前的要高,且未运行
|
||||
// 3. "待定更新"插件(插件未运行)
|
||||
return p == null ||
|
||||
(p.mInfo.getVersionValue() < info.getVersionValue() && !RePlugin.isPluginRunning(info.getName())) ||
|
||||
(info.getPendingUpdate() != null && !RePlugin.isPluginRunning(info.getName()));
|
||||
}
|
||||
|
||||
final Plugin loadPackageInfoPlugin(String plugin, PluginCommImpl pm) {
|
||||
Plugin p = Plugin.cloneAndReattach(mContext, mPlugins.get(plugin), mClassLoader, pm);
|
||||
return loadPlugin(p, Plugin.LOAD_INFO, true);
|
||||
|
@ -328,28 +328,45 @@ class PmHostSvc extends IPluginHost.Stub {
|
||||
}
|
||||
|
||||
if (pi != null) {
|
||||
// 插件是否需要更新
|
||||
if (!mPluginMgr.isNewOrUpdatedPlugin(pi)) {
|
||||
return pi;
|
||||
}
|
||||
|
||||
// 常驻进程上下文
|
||||
mPluginMgr.newPluginFound(pi, false);
|
||||
|
||||
// 通知其它进程
|
||||
Intent intent = new Intent(PmBase.ACTION_NEW_PLUGIN);
|
||||
intent.putExtra(RePluginConstants.KEY_PERSIST_NEED_RESTART, mNeedRestart);
|
||||
intent.putExtra("obj", pi);
|
||||
IPC.sendLocalBroadcast2AllSync(mContext, intent);
|
||||
|
||||
if (LOG) {
|
||||
LogDebug.d(PLUGIN_TAG, "pluginDownloaded complete, info=" + pi);
|
||||
}
|
||||
// 通常到这里,表示“安装已成功”,这时不管处于什么状态,都应该通知外界更新插件内存表
|
||||
syncPluginInfo2All(pi);
|
||||
}
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
private void syncPluginInfo2All(PluginInfo pi) {
|
||||
// PS:若更新了“正在运行”的插件(属于“下次重启进程后更新”),则由于install返回的是“新的PluginInfo”,为防止出现“错误更新”,需要使用原来的
|
||||
//
|
||||
// 举例,有一个正在运行的插件A(其Info为PluginInfoOld)升级到新版(其Info为PluginInfoNew),则:
|
||||
// 1. mManager.getService().install(path) 的返回值为:PluginInfoNew
|
||||
// 2. PluginInfoOld在常驻进程中的内容修改为:PluginInfoOld.mPendingUpdate = PendingInfoNew
|
||||
// 3. 同步到各进程,这里存在两种可能:
|
||||
// a) (有问题)同步的是PluginInfoNew,则所有进程的内存表都强制更新到新的Info上,因此【正在运行的】插件信息将丢失,会出现严重问题
|
||||
// b) (没问题)同步的是PluginInfoOld,只不过这个Old里面有个mPendingUpdate指向PendingInfoNew,则不会有问题,旧的仍被使用,符合预期
|
||||
// 4. 最终install方法的返回值是PluginInfoNew,这样最外面拿到的就是安装成功的新插件信息,符合开发者的预期
|
||||
PluginInfo needToSyncPi;
|
||||
PluginInfo parent = pi.getParentInfo();
|
||||
if (parent != null) {
|
||||
needToSyncPi = parent;
|
||||
} else {
|
||||
needToSyncPi = pi;
|
||||
}
|
||||
|
||||
// 在常驻进程内更新插件内存表
|
||||
mPluginMgr.newPluginFound(needToSyncPi, false);
|
||||
|
||||
// 通知其它进程去更新
|
||||
Intent intent = new Intent(PmBase.ACTION_NEW_PLUGIN);
|
||||
intent.putExtra(RePluginConstants.KEY_PERSIST_NEED_RESTART, mNeedRestart);
|
||||
intent.putExtra("obj", needToSyncPi);
|
||||
IPC.sendLocalBroadcast2AllSync(mContext, intent);
|
||||
|
||||
if (LOG) {
|
||||
LogDebug.d(TAG, "syncPluginInfo2All: Sync complete! syncPi=" + needToSyncPi);
|
||||
}
|
||||
}
|
||||
|
||||
private PluginInfo pluginDownloadedForPn(String path) {
|
||||
File f = new File(path);
|
||||
V5FileInfo v5f = V5FileInfo.build(f, V5FileInfo.NORMAL_PLUGIN);
|
||||
|
@ -34,8 +34,8 @@ import com.qihoo360.replugin.RePlugin;
|
||||
import com.qihoo360.replugin.RePluginInternal;
|
||||
import com.qihoo360.replugin.helper.JSONHelper;
|
||||
import com.qihoo360.replugin.helper.LogDebug;
|
||||
|
||||
import com.qihoo360.replugin.utils.FileUtils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@ -101,14 +101,18 @@ public class PluginInfo implements Parcelable, Cloneable {
|
||||
|
||||
// 若插件需要更新,则会有此值
|
||||
private PluginInfo mPendingUpdate;
|
||||
private boolean mIsThisPendingUpdateInfo;
|
||||
|
||||
// 若插件需要卸载,则会有此值
|
||||
private PluginInfo mPendingDelete;
|
||||
|
||||
// 若插件需要同版本覆盖安装更新,则会有此值
|
||||
private PluginInfo mPendingCover;
|
||||
private boolean mIsPendingCover;
|
||||
private boolean mIsPendingCover; // 若当前为“新的PluginInfo”且为“同版本覆盖”,则为了能区分路径,则需要将此字段同步到Json文件中
|
||||
|
||||
// 若当前为“新的PluginInfo”,则其“父Info”是什么?
|
||||
// 通常当前这个Info会包裹在“mPendingUpdate/mPendingDelete/mPendingCover”内
|
||||
// 此信息【不会】做持久化工作。下次重启进程后会消失
|
||||
private PluginInfo mParentInfo;
|
||||
|
||||
private PluginInfo(JSONObject jo) {
|
||||
initPluginInfo(jo);
|
||||
@ -150,7 +154,6 @@ public class PluginInfo implements Parcelable, Cloneable {
|
||||
*/
|
||||
public PluginInfo(PluginInfo pi) {
|
||||
this.mJson = JSONHelper.cloneNoThrows(pi.mJson);
|
||||
this.mIsThisPendingUpdateInfo = pi.mIsThisPendingUpdateInfo;
|
||||
if (pi.mPendingUpdate != null) {
|
||||
this.mPendingUpdate = new PluginInfo(pi.mPendingUpdate);
|
||||
}
|
||||
@ -161,6 +164,9 @@ public class PluginInfo implements Parcelable, Cloneable {
|
||||
if (pi.mPendingCover != null) {
|
||||
this.mPendingCover = new PluginInfo(pi.mPendingCover);
|
||||
}
|
||||
if (pi.mParentInfo != null) {
|
||||
this.mParentInfo = new PluginInfo(pi.mParentInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void initPluginInfo(JSONObject jo) {
|
||||
@ -206,11 +212,6 @@ public class PluginInfo implements Parcelable, Cloneable {
|
||||
*/
|
||||
public static PluginInfo parseFromPackageInfo(PackageInfo pi, String path) {
|
||||
ApplicationInfo ai = pi.applicationInfo;
|
||||
if (ai == null) {
|
||||
// 几乎不可能,但为保险起见,返回Null
|
||||
return null;
|
||||
}
|
||||
|
||||
String pn = pi.packageName;
|
||||
String alias = null;
|
||||
int low = 0;
|
||||
@ -322,9 +323,9 @@ public class PluginInfo implements Parcelable, Cloneable {
|
||||
if (isPnPlugin()) {
|
||||
// 为兼容以前逻辑,p-n仍是判断dex是否存在
|
||||
return isDexExtracted();
|
||||
} else if (isThisPendingUpdateInfo()) {
|
||||
} else if (getParentInfo() != null) {
|
||||
// 若PluginInfo是其它PluginInfo中的PendingUpdate,则返回那个PluginInfo的Used即可
|
||||
return RePlugin.isPluginUsed(getName());
|
||||
return getParentInfo().isUsed();
|
||||
} else {
|
||||
// 若是纯APK,且不是PendingUpdate,则直接从Json中获取
|
||||
return mJson.optBoolean("used");
|
||||
@ -625,9 +626,7 @@ public class PluginInfo implements Parcelable, Cloneable {
|
||||
setFrameworkVersion(frameVer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取JSON对象。仅内部使用
|
||||
*/
|
||||
// @hide
|
||||
public JSONObject getJSON() {
|
||||
return mJson;
|
||||
}
|
||||
@ -669,21 +668,17 @@ public class PluginInfo implements Parcelable, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 此PluginInfo是否是一个位于其它PluginInfo中的PendingUpdate?只在调用RePlugin.install方法才能看到 <p>
|
||||
* 注意:仅框架内部使用
|
||||
* 若此Info为“新PluginInfo”,则这里返回的是“其父Info”的内容。通常和PendingUpdate有关
|
||||
*
|
||||
* @return 是否是PendingUpdate的PluginInfo
|
||||
* @return 父PluginInfo
|
||||
*/
|
||||
public boolean isThisPendingUpdateInfo() {
|
||||
return mIsThisPendingUpdateInfo;
|
||||
public PluginInfo getParentInfo() {
|
||||
return mParentInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 此PluginInfo是否是一个位于其它PluginInfo中的PendingUpdate? <p>
|
||||
* 注意:仅框架内部使用
|
||||
*/
|
||||
public void setIsThisPendingUpdateInfo(boolean updateInfo) {
|
||||
mIsThisPendingUpdateInfo = updateInfo;
|
||||
// @hide
|
||||
public void setParentInfo(PluginInfo parent) {
|
||||
mParentInfo = parent;
|
||||
}
|
||||
|
||||
static PluginInfo createByJO(JSONObject jo) {
|
||||
@ -769,8 +764,8 @@ public class PluginInfo implements Parcelable, Cloneable {
|
||||
}
|
||||
|
||||
// 当前是否为PendingUpdate的信息
|
||||
if (mIsThisPendingUpdateInfo) {
|
||||
b.append("[isTPUI] ");
|
||||
if (mParentInfo != null) {
|
||||
b.append("[HAS_PARENT] ");
|
||||
}
|
||||
|
||||
// 插件类型
|
||||
|
@ -28,16 +28,16 @@ import com.qihoo360.loader2.CertUtils;
|
||||
import com.qihoo360.loader2.MP;
|
||||
import com.qihoo360.loader2.PluginNativeLibsHelper;
|
||||
import com.qihoo360.mobilesafe.api.Tasks;
|
||||
import com.qihoo360.replugin.utils.pkg.PackageFilesUtil;
|
||||
import com.qihoo360.replugin.RePlugin;
|
||||
import com.qihoo360.replugin.RePluginEventCallbacks;
|
||||
import com.qihoo360.replugin.RePluginInternal;
|
||||
import com.qihoo360.replugin.base.IPC;
|
||||
import com.qihoo360.replugin.utils.FileUtils;
|
||||
import com.qihoo360.replugin.helper.LogDebug;
|
||||
import com.qihoo360.replugin.helper.LogRelease;
|
||||
import com.qihoo360.replugin.model.PluginInfo;
|
||||
import com.qihoo360.replugin.model.PluginInfoList;
|
||||
import com.qihoo360.replugin.utils.FileUtils;
|
||||
import com.qihoo360.replugin.utils.pkg.PackageFilesUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -297,7 +297,6 @@ public class PluginManagerServer {
|
||||
}
|
||||
if (instPli.getVersion() > curPli.getVersion()) {
|
||||
// 高版本升级
|
||||
instPli.setIsThisPendingUpdateInfo(true);
|
||||
curPli.setPendingUpdate(instPli);
|
||||
curPli.setPendingDelete(null);
|
||||
curPli.setPendingCover(null);
|
||||
@ -313,6 +312,9 @@ public class PluginManagerServer {
|
||||
LogDebug.w(TAG, "updateOrLater: Plugin need update same version. clear PendingDelete.");
|
||||
}
|
||||
}
|
||||
|
||||
// 设置其Parent为curPli,在PmBase.newPluginFound时会用到
|
||||
instPli.setParentInfo(curPli);
|
||||
} else {
|
||||
if (LogDebug.LOG) {
|
||||
LogDebug.i(TAG, "updateOrLater: Not running. Update now! pn=" + curPli.getName());
|
||||
|
Loading…
Reference in New Issue
Block a user