Clean code (#863)
This commit is contained in:
parent
816de8cb85
commit
ca91e87aeb
|
|
@ -5,14 +5,3 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/build
|
/build
|
||||||
/captures
|
/captures
|
||||||
/release
|
|
||||||
.externalNativeBuild
|
|
||||||
elf-cleaner.sh
|
|
||||||
|
|
||||||
# vscode
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
.settings/
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
.cxx
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,6 @@
|
||||||
public static void showErrorToast(int);
|
public static void showErrorToast(int);
|
||||||
public static void setBinder(android.os.IBinder);
|
public static void setBinder(android.os.IBinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
-keepclassmembers class * implements android.os.Parcelable {
|
|
||||||
public static final ** CREATOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
|
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
|
||||||
public static void check*(...);
|
public static void check*(...);
|
||||||
public static void throw*(...);
|
public static void throw*(...);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import android.util.Log;
|
||||||
|
|
||||||
import org.lsposed.lspd.models.Application;
|
import org.lsposed.lspd.models.Application;
|
||||||
import org.lsposed.lspd.models.UserInfo;
|
import org.lsposed.lspd.models.UserInfo;
|
||||||
import org.lsposed.lspd.utils.ParceledListSlice;
|
|
||||||
import org.lsposed.manager.adapters.ScopeAdapter;
|
import org.lsposed.manager.adapters.ScopeAdapter;
|
||||||
import org.lsposed.manager.receivers.LSPManagerServiceHolder;
|
import org.lsposed.manager.receivers.LSPManagerServiceHolder;
|
||||||
|
|
||||||
|
|
@ -39,6 +38,8 @@ import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.github.xposed.xposedservice.utils.ParceledListSlice;
|
||||||
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
|
|
||||||
public static boolean isBinderAlive() {
|
public static boolean isBinderAlive() {
|
||||||
|
|
|
||||||
|
|
@ -131,9 +131,9 @@ public class CompileDialogFragment extends AppCompatDialogFragment {
|
||||||
result = "Error ";
|
result = "Error ";
|
||||||
}
|
}
|
||||||
if (TextUtils.isEmpty(err)) {
|
if (TextUtils.isEmpty(err)) {
|
||||||
return result + input.toString();
|
return result + input;
|
||||||
} else {
|
} else {
|
||||||
return result + err.toString();
|
return result + err;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
/.externalNativeBuild
|
|
||||||
/build
|
/build
|
||||||
/obj
|
|
||||||
/release
|
/release
|
||||||
*.iml
|
/src/main/cpp/main/src/config.cpp
|
||||||
/.cxx
|
|
||||||
src/main/cpp/main/src/config.cpp
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ dependencies {
|
||||||
implementation("de.upb.cs.swt:axml:2.1.1")
|
implementation("de.upb.cs.swt:axml:2.1.1")
|
||||||
compileOnly("androidx.annotation:annotation:1.2.0")
|
compileOnly("androidx.annotation:annotation:1.2.0")
|
||||||
compileOnly(project(":hiddenapi-stubs"))
|
compileOnly(project(":hiddenapi-stubs"))
|
||||||
implementation(project(":interface"))
|
|
||||||
implementation(project(":hiddenapi-bridge"))
|
implementation(project(":hiddenapi-bridge"))
|
||||||
implementation(project(":manager-service"))
|
implementation(project(":manager-service"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
-keep class de.robv.android.xposed.** {*;}
|
-keep class de.robv.android.xposed.** {*;}
|
||||||
-keep class android.** { *; }
|
-keep class android.** { *; }
|
||||||
-keepclassmembers class * implements android.os.Parcelable {
|
|
||||||
public static final ** CREATOR;
|
|
||||||
}
|
|
||||||
-keepclasseswithmembers class org.lsposed.lspd.core.Main {
|
-keepclasseswithmembers class org.lsposed.lspd.core.Main {
|
||||||
public static void forkSystemServerPost(android.os.IBinder);
|
public static void forkSystemServerPost(android.os.IBinder);
|
||||||
public static void forkAndSpecializePost(java.lang.String, java.lang.String, android.os.IBinder);
|
public static void forkAndSpecializePost(java.lang.String, java.lang.String, android.os.IBinder);
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,9 @@ public class HookMain {
|
||||||
private static void checkCompatibleMethods(Executable original, Method replacement, String replacementName) {
|
private static void checkCompatibleMethods(Executable original, Method replacement, String replacementName) {
|
||||||
ArrayList<Class<?>> originalParams;
|
ArrayList<Class<?>> originalParams;
|
||||||
if (original instanceof Method) {
|
if (original instanceof Method) {
|
||||||
originalParams = new ArrayList<>(Arrays.asList(((Method) original).getParameterTypes()));
|
originalParams = new ArrayList<>(Arrays.asList(original.getParameterTypes()));
|
||||||
} else if (original instanceof Constructor) {
|
} else if (original instanceof Constructor) {
|
||||||
originalParams = new ArrayList<>(Arrays.asList(((Constructor<?>) original).getParameterTypes()));
|
originalParams = new ArrayList<>(Arrays.asList(original.getParameterTypes()));
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Type of target method is wrong");
|
throw new IllegalArgumentException("Type of target method is wrong");
|
||||||
}
|
}
|
||||||
|
|
@ -71,8 +71,8 @@ public class HookMain {
|
||||||
ArrayList<Class<?>> replacementParams = new ArrayList<>(Arrays.asList(replacement.getParameterTypes()));
|
ArrayList<Class<?>> replacementParams = new ArrayList<>(Arrays.asList(replacement.getParameterTypes()));
|
||||||
|
|
||||||
if (original instanceof Method
|
if (original instanceof Method
|
||||||
&& !Modifier.isStatic(((Method) original).getModifiers())) {
|
&& !Modifier.isStatic(original.getModifiers())) {
|
||||||
originalParams.add(0, ((Method) original).getDeclaringClass());
|
originalParams.add(0, original.getDeclaringClass());
|
||||||
} else if (original instanceof Constructor) {
|
} else if (original instanceof Constructor) {
|
||||||
originalParams.add(0, ((Constructor<?>) original).getDeclaringClass());
|
originalParams.add(0, ((Constructor<?>) original).getDeclaringClass());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,13 @@ import org.lsposed.lspd.BuildConfig;
|
||||||
import org.lsposed.lspd.ILSPManagerService;
|
import org.lsposed.lspd.ILSPManagerService;
|
||||||
import org.lsposed.lspd.models.Application;
|
import org.lsposed.lspd.models.Application;
|
||||||
import org.lsposed.lspd.models.UserInfo;
|
import org.lsposed.lspd.models.UserInfo;
|
||||||
import org.lsposed.lspd.utils.ParceledListSlice;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
|
import io.github.xposed.xposedservice.utils.ParceledListSlice;
|
||||||
|
|
||||||
public class LSPManagerService extends ILSPManagerService.Stub {
|
public class LSPManagerService extends ILSPManagerService.Stub {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ import androidx.annotation.NonNull;
|
||||||
import org.lsposed.lspd.BuildConfig;
|
import org.lsposed.lspd.BuildConfig;
|
||||||
import org.lsposed.lspd.models.Application;
|
import org.lsposed.lspd.models.Application;
|
||||||
import org.lsposed.lspd.util.InstallerVerifier;
|
import org.lsposed.lspd.util.InstallerVerifier;
|
||||||
import org.lsposed.lspd.utils.ParceledListSlice;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
|
@ -67,6 +66,7 @@ import java.util.Set;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
import hidden.HiddenApiBridge;
|
import hidden.HiddenApiBridge;
|
||||||
|
import io.github.xposed.xposedservice.utils.ParceledListSlice;
|
||||||
|
|
||||||
public class PackageService {
|
public class PackageService {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,5 @@
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
# org.gradle.parallel=true
|
# org.gradle.parallel=true
|
||||||
#Sat Jan 30 19:20:27 CST 202130.0.322.0.7026061
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableResourceOptimizations=false
|
android.enableResourceOptimizations=false
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
/build
|
/build
|
||||||
/libs
|
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,6 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
dependencies {
|
||||||
resolutionStrategy {
|
api(project(":interface"))
|
||||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
-keepnames class * implements android.os.Parcelable
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package org.lsposed.lspd;
|
package org.lsposed.lspd;
|
||||||
|
|
||||||
import org.lsposed.lspd.utils.ParceledListSlice;
|
import io.github.xposed.xposedservice.utils.ParceledListSlice;
|
||||||
import org.lsposed.lspd.models.UserInfo;
|
import org.lsposed.lspd.models.UserInfo;
|
||||||
import org.lsposed.lspd.models.Application;
|
import org.lsposed.lspd.models.Application;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
package org.lsposed.lspd.utils;
|
|
||||||
|
|
||||||
parcelable ParceledListSlice<T>;
|
|
||||||
|
|
@ -1,193 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2011 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* 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 org.lsposed.lspd.utils;
|
|
||||||
|
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.util.Log;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.lsposed.lspd.managerservice.BuildConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transfer a large list of Parcelable objects across an IPC. Splits into
|
|
||||||
* multiple transactions if needed.
|
|
||||||
*
|
|
||||||
* Caveat: for efficiency and security, all elements must be the same concrete type.
|
|
||||||
* In order to avoid writing the class name of each object, we must ensure that
|
|
||||||
* each object is the same type, or else unparceling then reparceling the data may yield
|
|
||||||
* a different result if the class name encoded in the Parcelable is a Base type.
|
|
||||||
* See b/17671747.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
abstract class BaseParceledListSlice<T> implements Parcelable {
|
|
||||||
private static String TAG = "ParceledListSlice";
|
|
||||||
private static boolean DEBUG = BuildConfig.DEBUG;
|
|
||||||
/*
|
|
||||||
* TODO get this number from somewhere else. For now set it to a quarter of
|
|
||||||
* the 1MB limit.
|
|
||||||
*/
|
|
||||||
private static final int MAX_IPC_SIZE = 64 * 1024;
|
|
||||||
private final List<T> mList;
|
|
||||||
private int mInlineCountLimit = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
public BaseParceledListSlice(List<T> list) {
|
|
||||||
if(list == null) {
|
|
||||||
mList = Collections.emptyList();
|
|
||||||
} else {
|
|
||||||
mList = list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
BaseParceledListSlice(Parcel p, ClassLoader loader) {
|
|
||||||
final int N = p.readInt();
|
|
||||||
mList = new ArrayList<T>(N);
|
|
||||||
if (DEBUG) Log.d(TAG, "Retrieving " + N + " items");
|
|
||||||
if (N <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Parcelable.Creator<?> creator = readParcelableCreator(p, loader);
|
|
||||||
Class<?> listElementClass = null;
|
|
||||||
int i = 0;
|
|
||||||
while (i < N) {
|
|
||||||
if (p.readInt() == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
final T parcelable = readCreator(creator, p, loader);
|
|
||||||
if (listElementClass == null) {
|
|
||||||
listElementClass = parcelable.getClass();
|
|
||||||
} else {
|
|
||||||
verifySameType(listElementClass, parcelable.getClass());
|
|
||||||
}
|
|
||||||
mList.add(parcelable);
|
|
||||||
if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= N) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final IBinder retriever = p.readStrongBinder();
|
|
||||||
while (i < N) {
|
|
||||||
if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever);
|
|
||||||
Parcel data = Parcel.obtain();
|
|
||||||
Parcel reply = Parcel.obtain();
|
|
||||||
data.writeInt(i);
|
|
||||||
try {
|
|
||||||
retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (i < N && reply.readInt() != 0) {
|
|
||||||
final T parcelable = readCreator(creator, reply, loader);
|
|
||||||
verifySameType(listElementClass, parcelable.getClass());
|
|
||||||
mList.add(parcelable);
|
|
||||||
if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
reply.recycle();
|
|
||||||
data.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private T readCreator(Parcelable.Creator<?> creator, Parcel p, ClassLoader loader) {
|
|
||||||
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
|
|
||||||
Parcelable.ClassLoaderCreator<?> classLoaderCreator =
|
|
||||||
(Parcelable.ClassLoaderCreator<?>) creator;
|
|
||||||
return (T) classLoaderCreator.createFromParcel(p, loader);
|
|
||||||
}
|
|
||||||
return (T) creator.createFromParcel(p);
|
|
||||||
}
|
|
||||||
private static void verifySameType(final Class<?> expected, final Class<?> actual) {
|
|
||||||
if (!actual.equals(expected)) {
|
|
||||||
throw new IllegalArgumentException("Can't unparcel type "
|
|
||||||
+ (actual == null ? null : actual.getName()) + " in list of type "
|
|
||||||
+ (expected == null ? null : expected.getName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public List<T> getList() {
|
|
||||||
return mList;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Set a limit on the maximum number of entries in the array that will be included
|
|
||||||
* inline in the initial parcelling of this object.
|
|
||||||
*/
|
|
||||||
public void setInlineCountLimit(int maxCount) {
|
|
||||||
mInlineCountLimit = maxCount;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Write this to another Parcel. Note that this discards the internal Parcel
|
|
||||||
* and should not be used anymore. This is so we can pass this to a Binder
|
|
||||||
* where we won't have a chance to call recycle on this.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
final int N = mList.size();
|
|
||||||
final int callFlags = flags;
|
|
||||||
dest.writeInt(N);
|
|
||||||
if (DEBUG) Log.d(TAG, "Writing " + N + " items");
|
|
||||||
if (N > 0) {
|
|
||||||
final Class<?> listElementClass = mList.get(0).getClass();
|
|
||||||
writeParcelableCreator(mList.get(0), dest);
|
|
||||||
int i = 0;
|
|
||||||
while (i < N && i < mInlineCountLimit && dest.dataSize() < MAX_IPC_SIZE) {
|
|
||||||
dest.writeInt(1);
|
|
||||||
final T parcelable = mList.get(i);
|
|
||||||
verifySameType(listElementClass, parcelable.getClass());
|
|
||||||
writeElement(parcelable, dest, callFlags);
|
|
||||||
if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i < N) {
|
|
||||||
dest.writeInt(0);
|
|
||||||
Binder retriever = new Binder() {
|
|
||||||
@Override
|
|
||||||
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
|
|
||||||
throws RemoteException {
|
|
||||||
if (code != FIRST_CALL_TRANSACTION) {
|
|
||||||
return super.onTransact(code, data, reply, flags);
|
|
||||||
}
|
|
||||||
int i = data.readInt();
|
|
||||||
if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
|
|
||||||
while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
|
|
||||||
reply.writeInt(1);
|
|
||||||
final T parcelable = mList.get(i);
|
|
||||||
verifySameType(listElementClass, parcelable.getClass());
|
|
||||||
writeElement(parcelable, reply, callFlags);
|
|
||||||
if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i < N) {
|
|
||||||
if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
|
|
||||||
reply.writeInt(0);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever);
|
|
||||||
dest.writeStrongBinder(retriever);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected abstract void writeElement(T parcelable, Parcel reply, int callFlags);
|
|
||||||
protected abstract void writeParcelableCreator(T parcelable, Parcel dest);
|
|
||||||
protected abstract Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader);
|
|
||||||
}
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2011 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* 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 org.lsposed.lspd.utils;
|
|
||||||
|
|
||||||
import android.content.pm.ApplicationInfo;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.os.BadParcelableException;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transfer a large list of Parcelable objects across an IPC. Splits into
|
|
||||||
* multiple transactions if needed.
|
|
||||||
*
|
|
||||||
* @see BaseParceledListSlice
|
|
||||||
*/
|
|
||||||
public class ParceledListSlice<T extends Parcelable> extends BaseParceledListSlice<T> {
|
|
||||||
|
|
||||||
private static final String TAG = "ParceledListSlice";
|
|
||||||
|
|
||||||
// Cache of previously looked up CREATOR.createFromParcel() methods for
|
|
||||||
// particular classes. Keys are the names of the classes, values are
|
|
||||||
// Method objects.
|
|
||||||
private static final HashMap<ClassLoader, HashMap<String, Creator<?>>>
|
|
||||||
CREATORS = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
putCreator(PackageInfo.class.getName(), PackageInfo.CREATOR);
|
|
||||||
putCreator(ApplicationInfo.class.getName(), ApplicationInfo.CREATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void putCreator(String name, Parcelable.Creator<?> creator) {
|
|
||||||
HashMap<String, Parcelable.Creator<?>> map = CREATORS.get(null);
|
|
||||||
if (map == null) {
|
|
||||||
map = new HashMap<>();
|
|
||||||
CREATORS.put(null, map);
|
|
||||||
}
|
|
||||||
map.put(name, creator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParceledListSlice(List<T> list) {
|
|
||||||
super(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParceledListSlice(Parcel in, ClassLoader loader) {
|
|
||||||
super(in, loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Parcelable> ParceledListSlice<T> emptyList() {
|
|
||||||
return new ParceledListSlice<T>(Collections.<T>emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
int contents = 0;
|
|
||||||
final List<T> list = getList();
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
|
||||||
contents |= list.get(i).describeContents();
|
|
||||||
}
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeElement(T parcelable, Parcel dest, int callFlags) {
|
|
||||||
parcelable.writeToParcel(dest, callFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeParcelableCreator(T parcelable, Parcel dest) {
|
|
||||||
String name = parcelable.getClass().getName();
|
|
||||||
dest.writeString(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader) {
|
|
||||||
String name = from.readString();
|
|
||||||
if (name == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Parcelable.Creator<?> creator;
|
|
||||||
synchronized (CREATORS) {
|
|
||||||
HashMap<String, Parcelable.Creator<?>> map = CREATORS.get(loader);
|
|
||||||
if (map == null) {
|
|
||||||
map = new HashMap<>();
|
|
||||||
CREATORS.put(loader, map);
|
|
||||||
}
|
|
||||||
creator = map.get(name);
|
|
||||||
if (creator == null) {
|
|
||||||
try {
|
|
||||||
// If loader == null, explicitly emulate Class.forName(String) "caller
|
|
||||||
// classloader" behavior.
|
|
||||||
ClassLoader parcelableClassLoader =
|
|
||||||
(loader == null ? getClass().getClassLoader() : loader);
|
|
||||||
// Avoid initializing the Parcelable class until we know it implements
|
|
||||||
// Parcelable and has the necessary CREATOR field. http://b/1171613.
|
|
||||||
Class<?> parcelableClass = Class.forName(name, false /* initialize */,
|
|
||||||
parcelableClassLoader);
|
|
||||||
if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
|
|
||||||
throw new BadParcelableException("Parcelable protocol requires subclassing "
|
|
||||||
+ "from Parcelable on class " + name);
|
|
||||||
}
|
|
||||||
Field f = parcelableClass.getField("CREATOR");
|
|
||||||
if ((f.getModifiers() & Modifier.STATIC) == 0) {
|
|
||||||
throw new BadParcelableException("Parcelable protocol requires "
|
|
||||||
+ "the CREATOR object to be static on class " + name);
|
|
||||||
}
|
|
||||||
Class<?> creatorType = f.getType();
|
|
||||||
if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
|
|
||||||
// Fail before calling Field.get(), not after, to avoid initializing
|
|
||||||
// parcelableClass unnecessarily.
|
|
||||||
throw new BadParcelableException("Parcelable protocol requires a "
|
|
||||||
+ "Parcelable.Creator object called "
|
|
||||||
+ "CREATOR on class " + name);
|
|
||||||
}
|
|
||||||
creator = (Parcelable.Creator<?>) f.get(null);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
|
|
||||||
throw new BadParcelableException(
|
|
||||||
"IllegalAccessException when unmarshalling: " + name);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
Log.e(TAG, "Class not found when unmarshalling: " + name, e);
|
|
||||||
throw new BadParcelableException(
|
|
||||||
"ClassNotFoundException when unmarshalling: " + name);
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
throw new BadParcelableException("Parcelable protocol requires a "
|
|
||||||
+ "Parcelable.Creator object called "
|
|
||||||
+ "CREATOR on class " + name);
|
|
||||||
}
|
|
||||||
if (creator == null) {
|
|
||||||
throw new BadParcelableException("Parcelable protocol requires a "
|
|
||||||
+ "non-null Parcelable.Creator object called "
|
|
||||||
+ "CREATOR on class " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
map.put(name, creator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return creator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Parcelable.ClassLoaderCreator<ParceledListSlice> CREATOR =
|
|
||||||
new Parcelable.ClassLoaderCreator<ParceledListSlice>() {
|
|
||||||
public ParceledListSlice createFromParcel(Parcel in) {
|
|
||||||
return new ParceledListSlice(in, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ParceledListSlice createFromParcel(Parcel in, ClassLoader loader) {
|
|
||||||
return new ParceledListSlice(in, loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ParceledListSlice[] newArray(int size) {
|
|
||||||
return new ParceledListSlice[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
2
service
2
service
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1c5304e1519474771901b48f23fe23815defcd84
|
Subproject commit 18e53fa376d982731d6cf9ab02d592f6deae4210
|
||||||
Loading…
Reference in New Issue