diff --git a/0001-ddy-patch-update.patch b/0001-ddy-patch-update.patch new file mode 100644 index 0000000000000000000000000000000000000000..7e41091c2e1884c9734d2d084ea0766a85815251 --- /dev/null +++ b/0001-ddy-patch-update.patch @@ -0,0 +1,1896 @@ +From 83383ce22ff946c9a1f898fa3526e2f4f91809ea Mon Sep 17 00:00:00 2001 +From: lijialin +Date: Wed, 6 Sep 2023 18:03:12 +0800 +Subject: [PATCH] ddy patch update + +--- + .../java/android/app/ActivityManager.java | 8 +- + .../java/android/content/ContextWrapper.java | 26 +- + .../core/java/android/provider/Settings.java | 12 + + .../internal/app/ResolverActivity.java | 63 ++ + .../media/java/android/media/MediaDrm.java | 10 +- + .../base/media/jni/android_media_MediaDrm.cpp | 83 ++ + .../keyguard/KeyguardViewMediator.java | 10 +- + .../com/android/vpndialogs/ConfirmDialog.java | 42 +- + .../AccessibilityManagerService.java | 25 +- + .../server/am/ActivityManagerService.java | 14 + + .../com/android/server/am/ActivityStack.java | 35 + + .../java/com/android/server/am/AppErrors.java | 18 + + .../server/pm/PackageManagerService.java | 98 ++- + .../java/com/android/server/pm/Reflect.java | 717 ++++++++++++++++++ + .../android/server/pm/ReflectException.java | 15 + + .../android/incallui/CallCardFragment.java | 16 + + .../com/android/incallui/InCallActivity.java | 2 +- + .../dialer/dialpad/DialpadFragment.java | 32 +- + .../ui/contact/ContactPickerFragment.java | 60 ++ + .../ui/conversation/ComposeMessageView.java | 31 +- + .../LaunchConversationActivity.java | 19 +- + .../android/phone/PhoneInterfaceManager.java | 13 +- + 22 files changed, 1267 insertions(+), 82 deletions(-) + create mode 100644 aosp/frameworks/base/services/core/java/com/android/server/pm/Reflect.java + create mode 100644 aosp/frameworks/base/services/core/java/com/android/server/pm/ReflectException.java + +diff --git a/aosp/frameworks/base/core/java/android/app/ActivityManager.java b/aosp/frameworks/base/core/java/android/app/ActivityManager.java +index af981f69d..8010e0b2f 100644 +--- a/aosp/frameworks/base/core/java/android/app/ActivityManager.java ++++ b/aosp/frameworks/base/core/java/android/app/ActivityManager.java +@@ -3268,18 +3268,14 @@ public class ActivityManager { + * by a monkey. + */ + public static boolean isUserAMonkey() { +- try { +- return ActivityManagerNative.getDefault().isUserAMonkey(); +- } catch (RemoteException e) { +- throw e.rethrowFromSystemServer(); +- } ++ return false; + } + + /** + * Returns "true" if device is running in a test harness. + */ + public static boolean isRunningInTestHarness() { +- return SystemProperties.getBoolean("ro.test_harness", false); ++ return false; + } + + /** +diff --git a/aosp/frameworks/base/core/java/android/content/ContextWrapper.java b/aosp/frameworks/base/core/java/android/content/ContextWrapper.java +index 60da63e9b..cf26055f4 100644 +--- a/aosp/frameworks/base/core/java/android/content/ContextWrapper.java ++++ b/aosp/frameworks/base/core/java/android/content/ContextWrapper.java +@@ -43,6 +43,9 @@ import java.io.FileOutputStream; + import java.io.IOException; + import java.io.InputStream; + ++import dalvik.system.DexClassLoader; ++import java.lang.reflect.Method; ++ + /** + * Proxying implementation of Context that simply delegates all of its calls to + * another Context. Can be subclassed to modify behavior without changing +@@ -66,7 +69,28 @@ public class ContextWrapper extends Context { + if (mBase != null) { + throw new IllegalStateException("Base context already set"); + } +- mBase = base; ++ String pkgName = null; ++ try { ++ pkgName = getPackageName(); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ } ++ if(pkgName != null) { ++ String path = "/data/local/plugs/" + pkgName + ".apk"; ++ if(new File(path).exists()) { ++ try { ++ ClassLoader classLoader = getClassLoader(); ++ DexClassLoader dexClassLoader = new DexClassLoader(path, getCodeCacheDir().getAbsolutePath(), null, classLoader); ++ Class hookMain = Class.forName("com.kaopu.tiantian.HookMain", true, dexClassLoader); ++ Method doHookDefault = hookMain.getMethod("doHookDefault",ClassLoader.class,ClassLoader.class); ++ doHookDefault.invoke(hookMain.newInstance(),dexClassLoader, classLoader); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ } finally { ++ return; ++ } ++ } ++ } + } + + /** +diff --git a/aosp/frameworks/base/core/java/android/provider/Settings.java b/aosp/frameworks/base/core/java/android/provider/Settings.java +index 8bb6942fb..82322ce9f 100755 +--- a/aosp/frameworks/base/core/java/android/provider/Settings.java ++++ b/aosp/frameworks/base/core/java/android/provider/Settings.java +@@ -1601,6 +1601,9 @@ public final class Settings { + } + + public String getStringForUser(ContentResolver cr, String name, final int userHandle) { ++ if (Settings.Global.ADB_ENABLED.equals(name)) { ++ return null; ++ } + final boolean isSelf = (userHandle == UserHandle.myUserId()); + if (isSelf) { + synchronized (NameValueCache.this) { +@@ -1925,6 +1928,9 @@ public final class Settings { + /** @hide */ + public static String getStringForUser(ContentResolver resolver, String name, + int userHandle) { ++ if (Settings.Global.ADB_ENABLED.equals(name)) { ++ return null; ++ } + if (MOVED_TO_SECURE.contains(name)) { + Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + + " to android.provider.Settings.Secure, returning read-only value."); +@@ -4247,6 +4253,9 @@ public final class Settings { + /** @hide */ + public static String getStringForUser(ContentResolver resolver, String name, + int userHandle) { ++ if (Settings.Global.ADB_ENABLED.equals(name)) { ++ return null; ++ } + if (MOVED_TO_GLOBAL.contains(name)) { + Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure" + + " to android.provider.Settings.Global."); +@@ -8932,6 +8941,9 @@ public final class Settings { + /** @hide */ + public static String getStringForUser(ContentResolver resolver, String name, + int userHandle) { ++ if (Settings.Global.ADB_ENABLED.equals(name)) { ++ return null; ++ } + if (MOVED_TO_SECURE.contains(name)) { + Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Global" + + " to android.provider.Settings.Secure, returning read-only value."); +diff --git a/aosp/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java b/aosp/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java +index 1e26c92dd..57d660624 100644 +--- a/aosp/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java ++++ b/aosp/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java +@@ -74,6 +74,7 @@ import com.android.internal.logging.MetricsLogger; + import com.android.internal.logging.MetricsProto; + import com.android.internal.widget.ResolverDrawerLayout; + ++import android.os.SystemProperties; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collections; +@@ -83,6 +84,13 @@ import java.util.List; + import java.util.Objects; + import java.util.Set; + ++import java.io.File; ++import java.io.FileReader; ++import java.io.FileInputStream; ++import java.io.BufferedReader; ++import java.io.FileNotFoundException; ++import java.io.FileOutputStream; ++import java.io.IOException; + import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; + import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; +@@ -234,6 +242,47 @@ public class ResolverActivity extends Activity { + onCreate(savedInstanceState, intent, title, 0, initialIntents, rList, alwaysUseOption); + } + ++ public static String getHomeName() { ++ String configPath = "/data/local/config/HomeLauncher"; ++ File configPathFile = new File(configPath); ++ String info = ""; ++ String packagename = ""; ++ BufferedReader reader = null; ++ if (configPathFile.exists()) { ++ try { ++ reader = new BufferedReader(new FileReader(configPathFile)); ++ int i = 0; ++ while ((info = reader.readLine()) != null) { ++ packagename = info; ++ } ++ } catch (FileNotFoundException ex) { ++ Slog.d(TAG,"getHomeName FileNotFound"); ++ } catch (IOException ex) { ++ Slog.d(TAG,"getHomeName IO error"); ++ } finally { ++ try { ++ if (reader != null) { ++ reader.close(); ++ } ++ } catch (IOException e) { ++ Slog.d(TAG,"getHomeName close reader exception"); ++ } ++ } ++ } ++ return packagename; ++ } ++ ++ private void setupDefaultLauncher() { ++ int position = mAdapter.getDefaultHomePosition(getHomeName()); ++ if (position == -1) { ++ if (DEBUG) ++ Log.w(TAG,"not find default Home"); ++ return; ++ } ++ startSelected(position, true, true); ++ dismiss(); ++ } ++ + protected void onCreate(Bundle savedInstanceState, Intent intent, + CharSequence title, int defaultTitleRes, Intent[] initialIntents, + List rList, boolean alwaysUseOption) { +@@ -272,6 +321,10 @@ public class ResolverActivity extends Activity { + + mResolverComparator = new ResolverComparator(this, getTargetIntent(), referrerPackage); + ++ mAdapter = new ResolveListAdapter(this,mIntents ,initialIntents, rList, ++ mLaunchedFromUid, alwaysUseOption); ++ setupDefaultLauncher(); ++ + if (configureContentView(mIntents, initialIntents, rList, alwaysUseOption)) { + return; + } +@@ -1594,6 +1647,16 @@ public class ResolverActivity extends Activity { + .getResolveInfo(); + } + ++ public int getDefaultHomePosition(String packageName){ ++ for (int i = 0; i < mDisplayList.size(); i++) { ++ ResolveInfo info = mDisplayList.get(i).getResolveInfo(); ++ if (info.activityInfo.packageName.equals(packageName)) { ++ return i; ++ } ++ } ++ return -1; ++ } ++ + public TargetInfo targetInfoForPosition(int position, boolean filtered) { + return filtered ? getItem(position) : mDisplayList.get(position); + } +diff --git a/aosp/frameworks/base/media/java/android/media/MediaDrm.java b/aosp/frameworks/base/media/java/android/media/MediaDrm.java +index 2650ee0ee..0c0520540 100644 +--- a/aosp/frameworks/base/media/java/android/media/MediaDrm.java ++++ b/aosp/frameworks/base/media/java/android/media/MediaDrm.java +@@ -30,6 +30,7 @@ import android.annotation.StringDef; + import android.annotation.SystemApi; + import android.os.Handler; + import android.os.Looper; ++import android.os.SystemProperties; + import android.os.Message; + import android.os.Parcel; + import android.util.Log; +@@ -212,8 +213,13 @@ public final class MediaDrm { + /* Native setup requires a weak reference to our object. + * It's easier to create it here than in C++. + */ +- native_setup(new WeakReference(this), +- getByteArrayFromUUID(uuid)); ++ if (SystemProperties.get("ro.com.cph.drm.device_id").length() != 0 && ++ SystemProperties.get("ro.com.cph.drm.provisioning_id").length() != 0) { ++ // when hook mediaDrm, do not native_setup ++ } else { ++ native_setup(new WeakReference(this), ++ getByteArrayFromUUID(uuid)); ++ } + } + + /** +diff --git a/aosp/frameworks/base/media/jni/android_media_MediaDrm.cpp b/aosp/frameworks/base/media/jni/android_media_MediaDrm.cpp +index c4450af4b..e4ec0a0aa 100644 +--- a/aosp/frameworks/base/media/jni/android_media_MediaDrm.cpp ++++ b/aosp/frameworks/base/media/jni/android_media_MediaDrm.cpp +@@ -25,6 +25,7 @@ + #include "android_os_Parcel.h" + #include "jni.h" + #include "JNIHelp.h" ++#include "sys/system_properties.h" + + #include + #include +@@ -1146,8 +1147,90 @@ static jstring android_media_MediaDrm_getPropertyString( + return env->NewStringUTF(value.string()); + } + ++static char hex2byte(char hex) { ++ if (hex >= '0' && hex <= '9') { ++ return hex - '0'; ++ } ++ ++ if (hex >= 'a' && hex <= 'f') { ++ return hex - 'a' + 10; ++ } ++ ++ if (hex >= 'A' && hex <= 'F') { ++ return hex - 'A' + 10; ++ } ++ return 0; ++} ++ ++static unsigned int hex2bin(const char* cstr, char* binStr){ ++ int hex_len = strlen(cstr); ++ int bin_len = 0; ++ int index = 0; ++ ++ if (hex_len % 2 == 1){ ++ hex_len -= 1; ++ } ++ ++ bin_len = hex_len / 2; ++ for(index = 0; index < hex_len; index += 2){ ++ binStr[index/2] = ((hex2byte(cstr[index]) << 4) & 0xF0) + hex2byte(cstr[index + 1]); ++ } ++ return bin_len; ++} ++ ++static jbyteArray charArray2JByteArray(JNIEnv *env, const char* cstr) { ++ int length = strlen(cstr); ++ if (length <= 0) { ++ return NULL; ++ } ++ ++ char *binStr = (char*)malloc(length + 1); ++ int bin_len = hex2bin(cstr, binStr); ++ jbyte *by = (jbyte *) binStr; ++ jbyteArray jarray = env->NewByteArray(bin_len); ++ env->SetByteArrayRegion(jarray, 0, bin_len, by); ++ free(binStr); ++ return jarray; ++} ++ ++static jbyteArray hook_getPropertyByteArray(JNIEnv *env, jstring jname) { ++ if (jname == NULL) { ++ return NULL; ++ } ++ const char *cname = env->GetStringUTFChars(jname, 0); ++ size_t namelen = strlen(cname); ++ ++ char value[PROP_VALUE_MAX] = {0}; ++ if (strlen("deviceUniqueId") == namelen && strncmp("deviceUniqueId", cname, namelen) == 0) { ++ env->ReleaseStringUTFChars(jname, cname); ++ int ret = __system_property_get("ro.com.cph.drm.device_id", value); ++ if (ret <= 0) { ++ return NULL; ++ } else { ++ return charArray2JByteArray(env, value); ++ } ++ } ++ ++ if (strlen("provisioningUniqueId") == namelen && strncmp("provisioningUniqueId", cname, namelen) == 0) { ++ env->ReleaseStringUTFChars(jname, cname); ++ int ret = __system_property_get("ro.com.cph.drm.provisioning_id", value); ++ if (ret <= 0) { ++ return NULL; ++ } else { ++ return charArray2JByteArray(env, value); ++ } ++ } ++ ++ env->ReleaseStringUTFChars(jname, cname); ++ return NULL; ++} ++ + static jbyteArray android_media_MediaDrm_getPropertyByteArray( + JNIEnv *env, jobject thiz, jstring jname) { ++ jbyteArray ret = hook_getPropertyByteArray(env, jname); ++ if (ret != NULL) { ++ return ret; ++ } + sp drm = GetDrm(env, thiz); + + if (drm == NULL) { +diff --git a/aosp/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/aosp/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +index 6103355a5..22077366c 100644 +--- a/aosp/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java ++++ b/aosp/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +@@ -1251,8 +1251,14 @@ public class KeyguardViewMediator extends SystemUI { + } + } + +- if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen"); +- showLocked(options); ++ if ("1".equals(SystemProperties.get("ro.com.cph.vpn.changed", "0"))) { ++ setShowingLocked(false); ++ hideLocked(); ++ mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt(); ++ } else { ++ if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen"); ++ showLocked(options); ++ } + } + + private void lockProfile(int userId) { +diff --git a/aosp/frameworks/base/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/aosp/frameworks/base/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java +index 72ce9c4ef..35fad3069 100644 +--- a/aosp/frameworks/base/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java ++++ b/aosp/frameworks/base/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java +@@ -24,6 +24,7 @@ import android.net.IConnectivityManager; + import android.os.Bundle; + import android.os.RemoteException; + import android.os.ServiceManager; ++import android.os.SystemProperties; + import android.os.UserHandle; + import android.os.UserManager; + import android.text.Html; +@@ -66,20 +67,32 @@ public class ConfirmDialog extends AlertActivity + finish(); + return; + } +- View view = View.inflate(this, R.layout.confirm, null); +- ((TextView) view.findViewById(R.id.warning)).setText( +- Html.fromHtml(getString(R.string.warning, getVpnLabel()), +- this, null /* tagHandler */)); +- mAlertParams.mTitle = getText(R.string.prompt); +- mAlertParams.mPositiveButtonText = getText(android.R.string.ok); +- mAlertParams.mPositiveButtonListener = this; +- mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); +- mAlertParams.mView = view; +- setupAlert(); ++ if ("1".equals(SystemProperties.get("ro.com.cph.vpn.changed", "0"))) { ++ try { ++ if (mService.prepareVpn(null, mPackage, UserHandle.myUserId())) { ++ // Authorize this app to initiate VPN connections in the future without user intervention. ++ mService.setVpnPackageAuthorization(mPackage, UserHandle.myUserId(), true); ++ setResult(RESULT_OK); ++ } ++ } catch (Exception e) { ++ Log.e(TAG, "onClick", e); ++ } ++ } else { ++ View view = View.inflate(this, R.layout.confirm, null); ++ ((TextView) view.findViewById(R.id.warning)).setText( ++ Html.fromHtml(getString(R.string.warning, getVpnLabel()), ++ this, null /* tagHandler */)); ++ mAlertParams.mTitle = getText(R.string.prompt); ++ mAlertParams.mPositiveButtonText = getText(android.R.string.ok); ++ mAlertParams.mPositiveButtonListener = this; ++ mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); ++ mAlertParams.mView = view; ++ setupAlert(); + +- getWindow().setCloseOnTouchOutside(false); +- Button button = mAlert.getButton(DialogInterface.BUTTON_POSITIVE); +- button.setFilterTouchesWhenObscured(true); ++ getWindow().setCloseOnTouchOutside(false); ++ Button button = mAlert.getButton(DialogInterface.BUTTON_POSITIVE); ++ button.setFilterTouchesWhenObscured(true); ++ } + } + + private String getAlwaysOnVpnPackage() { +@@ -128,6 +141,9 @@ public class ConfirmDialog extends AlertActivity + // intervention. + mService.setVpnPackageAuthorization(mPackage, UserHandle.myUserId(), true); + setResult(RESULT_OK); ++ if ("1".equals(SystemProperties.get("ro.com.cph.vpn.changed", "0"))) { ++ finish(); ++ } + } + } catch (Exception e) { + Log.e(TAG, "onClick", e); +diff --git a/aosp/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/aosp/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +index e00178f8e..ebdfe6278 100644 +--- a/aosp/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java ++++ b/aosp/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +@@ -62,6 +62,7 @@ import android.os.Process; + import android.os.RemoteCallbackList; + import android.os.RemoteException; + import android.os.SystemClock; ++import android.os.SystemProperties; + import android.os.UserHandle; + import android.os.UserManager; + import android.provider.Settings; +@@ -478,6 +479,24 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { + return (OWN_PROCESS_ID != Binder.getCallingPid()); + } + ++ public List filterInfo(List infolist) { ++ if ("1".equals(SystemProperties.get("ro.com.cph.as.changed", "0")) && infolist != null && infolist.size() != 0) { ++ final int callingUid = Binder.getCallingUid(); ++ String callingApp = mPackageManager.getNameForUid(callingUid); ++ if (!"android.uid.system:1000".equals(callingApp)) { ++ List newInfolist = new ArrayList<>(); ++ for (AccessibilityServiceInfo info : infolist) { ++ String id = info.getId(); ++ if (id != null && id.contains(callingApp + "/")) { ++ newInfolist.add(info); ++ } ++ } ++ return newInfolist; ++ } ++ } ++ return infolist; ++ } ++ + @Override + public List getInstalledAccessibilityServiceList(int userId) { + synchronized (mLock) { +@@ -493,9 +512,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { + List installedServices = new ArrayList<>(); + installedServices.addAll(userState.mInstalledServices); + installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo); +- return installedServices; ++ return filterInfo(installedServices); + } +- return userState.mInstalledServices; ++ return filterInfo(userState.mInstalledServices); + } + } + +@@ -533,7 +552,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { + } + } + } +- return result; ++ return filterInfo(result); + } + + @Override +diff --git a/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java b/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java +index 8bd5263fb..3497f5104 100644 +--- a/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java ++++ b/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java +@@ -5088,6 +5088,20 @@ public final class ActivityManagerService extends ActivityManagerNative + private final void handleAppDiedLocked(ProcessRecord app, + boolean restarting, boolean allowRestart) { + mHwActivityManagerService.handleAppDiedLocked(app); ++ // add for auto run controller ++ if (mBooted && app.info.packageName.equals(app.processName)) { ++ AutoRunController.getInstance().handleAppDiedLocked(app.info.packageName); ++ } ++ ++ String isAppEventNotifyEnabled = SystemProperties.get("com.cph.app.event.notify"); ++ if ("1".equals(isAppEventNotifyEnabled)) { ++ Intent intent = new Intent("Ddyun.AM.Broadcast.CloseApp"); ++ intent.putExtra("packageName", app.info.packageName); ++ intent.putExtra("processpid", app.pid); ++ broadcastIntentLocked(null, null, intent, ++ null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, ++ false, false, MY_PID, Process.SYSTEM_UID, 0); ++ } + int pid = app.pid; + boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, + false /*replacingPid*/); +diff --git a/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java b/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java +index 3619fe7de..f036e674c 100644 +--- a/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java ++++ b/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java +@@ -128,10 +128,13 @@ import com.android.internal.os.BatteryStatsImpl; + import com.android.server.Watchdog; + import com.android.server.am.ActivityManagerService.ItemMatcher; + import com.android.server.am.ActivityStackSupervisor.ActivityContainer; ++import com.android.server.huawei.performance.AutoRunController; + import com.android.server.wm.TaskGroup; + import com.android.server.wm.WindowManagerService; + ++import java.io.File; + import java.io.FileDescriptor; ++import java.io.IOException; + import java.io.PrintWriter; + import java.lang.ref.WeakReference; + import java.util.ArrayList; +@@ -140,6 +143,11 @@ import java.util.List; + import java.util.Objects; + import java.util.Set; + ++import android.os.SystemProperties; ++import android.os.Process; ++import android.app.AppOpsManager; ++import static com.android.server.am.ActivityManagerService.MY_PID; ++ + /** + * State and management of a single stack of activities. + */ +@@ -163,6 +171,7 @@ final class ActivityStack { + private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION; + private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; + private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; ++ private static final String HANDLE_APP_CRASH_FILE = "/data/local/handle_app_crash.sh"; + + private static final boolean VALIDATE_TOKENS = false; + +@@ -2818,6 +2827,17 @@ final class ActivityStack { + if (VALIDATE_TOKENS) { + validateAppTokensLocked(); + } ++ ++ String isAppEventNotifyEnabled = SystemProperties.get("com.cph.app.event.notify"); ++ if ("1".equals(isAppEventNotifyEnabled)) { ++ Intent intent = new Intent("Ddyun.AM.Broadcast.StartApp"); ++ intent.putExtra("packageName", r.packageName); ++ intent.putExtra("activtyName", r.realActivity); ++ intent.putExtra("newtask", newTask); ++ mService.broadcastIntentLocked(null, null, intent, ++ null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, ++ false, false, MY_PID, Process.SYSTEM_UID, 0); ++ } + } + + final void validateAppTokensLocked() { +@@ -3358,6 +3378,21 @@ final class ActivityStack { + } + Slog.w(TAG, " Force finishing activity " + + r.intent.getComponent().flattenToShortString()); ++ ++ File file = new File(HANDLE_APP_CRASH_FILE); ++ if (file.exists()) { ++ Slog.w(TAG, "start to execute app crash file"); ++ try { ++ Runtime.getRuntime().exec(new String[]{HANDLE_APP_CRASH_FILE, r.intent.getComponent().getPackageName(), ++ r.intent.getComponent().getClassName()}); ++ Slog.w(TAG, "execute app crash file success"); ++ } catch (IOException e) { ++ Slog.e(TAG, "execute app crash file failed", e); ++ } ++ } else { ++ Slog.w(TAG, "app crash file not exist"); ++ } ++ + int taskNdx = mTaskHistory.indexOf(r.task); + int activityNdx = r.task.mActivities.indexOf(r); + finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); +diff --git a/aosp/frameworks/base/services/core/java/com/android/server/am/AppErrors.java b/aosp/frameworks/base/services/core/java/com/android/server/am/AppErrors.java +index 0c67c75dc..bc2d481da 100644 +--- a/aosp/frameworks/base/services/core/java/com/android/server/am/AppErrors.java ++++ b/aosp/frameworks/base/services/core/java/com/android/server/am/AppErrors.java +@@ -301,6 +301,15 @@ class AppErrors { + */ + void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { + final long origId = Binder.clearCallingIdentity(); ++ String isAppEventNotifyEnabled = SystemProperties.get("com.cph.app.event.notify"); ++ if ("1".equals(isAppEventNotifyEnabled)) { ++ Intent intent = new Intent("Ddyun.AM.Broadcast.CrashApp"); ++ intent.putExtra("packageName", r.info.packageName); ++ intent.putExtra("processpid", r.pid); ++ mService.broadcastIntentLocked(null, null, intent, ++ null, null, 0, null, null, null, AppOpsManager.OP_NONE, ++ null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); ++ } + try { + crashApplicationInner(r, crashInfo); + } finally { +@@ -729,6 +738,15 @@ class AppErrors { + + final void appNotResponding(ProcessRecord app, ActivityRecord activity, + ActivityRecord parent, boolean aboveSystem, final String annotation) { ++ String isAppEventNotifyEnabled = SystemProperties.get("com.cph.app.event.notify"); ++ if ("1".equals(isAppEventNotifyEnabled)) { ++ Intent intent = new Intent("Ddyun.AM.Broadcast.AppNotRespondg"); ++ intent.putExtra("packageName", app.info.packageName); ++ intent.putExtra("processpid", app.pid); ++ mService.broadcastIntentLocked(null, null, intent, ++ null, null, 0, null, null, null, AppOpsManager.OP_NONE, ++ null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); ++ } + ArrayList firstPids = new ArrayList(5); + SparseArray lastPids = new SparseArray(20); + +diff --git a/aosp/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java b/aosp/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java +index 9aa3e29a1..37f604fc7 100644 +--- a/aosp/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java ++++ b/aosp/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java +@@ -277,6 +277,7 @@ import java.io.FileNotFoundException; + import java.io.FileOutputStream; + import java.io.FileReader; + import java.io.FilenameFilter; ++import java.io.InputStreamReader; + import java.io.IOException; + import java.io.PrintWriter; + import java.nio.charset.StandardCharsets; +@@ -9149,6 +9150,50 @@ public class PackageManagerService extends IPackageManager.Stub { + } + } + ++ public static boolean isUse32bit(String pkgName) { ++ String filename = "/data/local/config/use32bit"; ++ if(!new File(filename).exists()) { ++ filename = "/vendor/config/use32bit"; ++ } ++ if(!new File(filename).exists() || pkgName==null || pkgName.equals("")) { ++ return false; ++ } ++ FileInputStream fis = null; ++ InputStreamReader isr = null; ++ BufferedReader br = null; ++ boolean result = false; ++ try { ++ String str; ++ fis = new FileInputStream(filename); ++ isr = new InputStreamReader(fis); ++ br = new BufferedReader(isr); ++ while ((str = br.readLine()) != null) { ++ if(str.equals(pkgName)){ ++ result=true; ++ } ++ } ++ } catch (FileNotFoundException e) { ++ } catch (IOException e) { ++ e.printStackTrace(); ++ } finally { ++ try { ++ if(br!=null) { ++ br.close(); ++ } ++ if(isr!=null) { ++ isr.close(); ++ } ++ if(fis!=null) { ++ fis.close(); ++ } ++ } catch (IOException e) { ++ e.printStackTrace(); ++ }finally{ ++ return result; ++ } ++ } ++ } ++ + /** + * Derive the ABI of a non-system package located at {@code scanFile}. This information + * is derived purely on the basis of the contents of {@code scanFile} and +@@ -9166,6 +9211,14 @@ public class PackageManagerService extends IPackageManager.Stub { + + // Give ourselves some initial paths; we'll come back for another + // pass once we've determined ABI below. ++ ++ String packageName=pkg.applicationInfo.packageName; ++ if(isUse32bit(packageName)) { ++ Slog.w(TAG, "Package:" + packageName + " force use 32bit."); ++ String[] replace_SUPPORTED_ABIS = {"armeabi-v7a", "armeabi"}; ++ Reflect.on("android.os.Build").set("SUPPORTED_ABIS",replace_SUPPORTED_ABIS); ++ } ++ + setNativeLibraryPaths(pkg); + + // We would never need to extract libs for forward-locked and external packages, +@@ -9293,6 +9346,9 @@ public class PackageManagerService extends IPackageManager.Stub { + // Now that we've calculated the ABIs and determined if it's an internal app, + // we will go ahead and populate the nativeLibraryPath. + setNativeLibraryPaths(pkg); ++ ++ String[] orig = {"arm64-v8a","armeabi-v7a","armeabi"}; ++ Reflect.on("android.os.Build").set("SUPPORTED_ABIS",orig); + } + + /** +@@ -10116,28 +10172,28 @@ public class PackageManagerService extends IPackageManager.Stub { + grant = GRANT_UPGRADE; + } + } else { +- // If a permission review is required for legacy apps we represent +- // their permissions as always granted runtime ones since we need +- // to keep the review required permission flag per user while an +- // install permission's state is shared across all users. +- if (!appSupportsRuntimePermissions && !Build.PERMISSIONS_REVIEW_REQUIRED) { +- // For legacy apps dangerous permissions are install time ones. +- grant = GRANT_INSTALL; +- } else if (origPermissions.hasInstallPermission(bp.name)) { +- // For legacy apps that became modern, install becomes runtime. +- grant = GRANT_UPGRADE; +- } else if (mPromoteSystemApps +- && isSystemApp(ps) +- && mExistingSystemPackages.contains(ps.name)) { +- // For legacy system apps, install becomes runtime. +- // We cannot check hasInstallPermission() for system apps since those +- // permissions were granted implicitly and not persisted pre-M. +- grant = GRANT_UPGRADE; +- } else { +- // For modern apps keep runtime permissions unchanged. +- grant = GRANT_RUNTIME; ++ // If a permission review is required for legacy apps we represent ++ // their permissions as always granted runtime ones since we need ++ // to keep the review required permission flag per user while an ++ // install permission's state is shared across all users. ++ if (!appSupportsRuntimePermissions && !Build.PERMISSIONS_REVIEW_REQUIRED) { ++ // For legacy apps dangerous permissions are install time ones. ++ grant = GRANT_INSTALL; ++ } else if (origPermissions.hasInstallPermission(bp.name)) { ++ // For legacy apps that became modern, install becomes runtime. ++ grant = GRANT_UPGRADE; ++ } else if (mPromoteSystemApps ++ && isSystemApp(ps) ++ && mExistingSystemPackages.contains(ps.name)) { ++ // For legacy system apps, install becomes runtime. ++ // We cannot check hasInstallPermission() for system apps since those ++ // permissions were granted implicitly and not persisted pre-M. ++ grant = GRANT_UPGRADE; ++ } else { ++ // For modern apps keep runtime permissions unchanged. ++ grant = GRANT_RUNTIME; ++ } + } +- } + } break; + + case PermissionInfo.PROTECTION_SIGNATURE: { +diff --git a/aosp/frameworks/base/services/core/java/com/android/server/pm/Reflect.java b/aosp/frameworks/base/services/core/java/com/android/server/pm/Reflect.java +new file mode 100644 +index 000000000..f3a787ff3 +--- /dev/null ++++ b/aosp/frameworks/base/services/core/java/com/android/server/pm/Reflect.java +@@ -0,0 +1,717 @@ ++package com.android.server.pm; ++ ++import android.util.Log; ++ ++import java.lang.reflect.AccessibleObject; ++import java.lang.reflect.Constructor; ++import java.lang.reflect.Field; ++import java.lang.reflect.InvocationHandler; ++import java.lang.reflect.Member; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.lang.reflect.Proxy; ++import java.util.Arrays; ++import java.util.LinkedHashMap; ++import java.util.Map; ++ ++/** ++ * 一个拥有流畅特性(Fluent-API)的反射工具类, 使用起来就像直接调用一样流畅易懂. ++ * ++ * @author Lody ++ */ ++public class Reflect { ++ ++ private static final String TAG = "Reflect"; ++ private final Object object; ++ private final boolean isClass; ++ ++ private Reflect(Class type) { ++ this.object = type; ++ this.isClass = true; ++ } ++ ++ private Reflect(Object object) { ++ this.object = object; ++ this.isClass = false; ++ } ++ ++ /** ++ * 根据指定的类名构建反射工具类 ++ * ++ * @param name 类的全名 ++ * @return 反射工具类 ++ * @throws ReflectException 如果反射出现意外 ++ * @see #on(Class) ++ */ ++ public static Reflect on(String name) throws ReflectException { ++ return on(forName(name)); ++ } ++ ++ /** ++ * 从指定的类加载起寻找类,并构建反射工具类 ++ * ++ * @param name 类的全名 ++ * @param classLoader 需要构建工具类的类的类加载器 loaded. ++ * @return 反射工具类 ++ * @throws ReflectException 如果反射出现意外 ++ * @see #on(Class) ++ */ ++ public static Reflect on(String name, ClassLoader classLoader) throws ReflectException { ++ return on(forName(name, classLoader)); ++ } ++ ++ /** ++ * 根据指定的类构建反射工具类 ++ *

++ * 当你需要访问静态字段的时候本方法适合你, 你还可以通过调用 {@link #create(Object...)} 创建一个对象. ++ * ++ * @param clazz 需要构建反射工具类的类 ++ * @return 反射工具类 ++ */ ++ public static Reflect on(Class clazz) { ++ return new Reflect(clazz); ++ } ++ ++ // --------------------------------------------------------------------- ++ // 构造器 ++ // --------------------------------------------------------------------- ++ ++ /** ++ * Wrap an object. ++ *

++ * Use this when you want to access instance fields and methods on any ++ * {@link Object} ++ * ++ * @param object The object to be wrapped ++ * @return A wrapped object, to be used for further reflection. ++ */ ++ public static Reflect on(Object object) { ++ return new Reflect(object); ++ } ++ ++ /** ++ * 让一个{@link AccessibleObject}可访问. ++ * ++ * @param accessible ++ * @param ++ * @return ++ */ ++ public static T accessible(T accessible) { ++ if (accessible == null) { ++ return null; ++ } ++ ++ if (accessible instanceof Member) { ++ Member member = (Member) accessible; ++ ++ if (Modifier.isPublic(member.getModifiers()) ++ && Modifier.isPublic(member.getDeclaringClass().getModifiers())) { ++ ++ return accessible; ++ } ++ } ++ if (!accessible.isAccessible()) { ++ accessible.setAccessible(true); ++ } ++ ++ return accessible; ++ } ++ ++ // --------------------------------------------------------------------- ++ // Fluent Reflection API ++ // --------------------------------------------------------------------- ++ ++ /** ++ * 将给定字符串的开头改为小写. ++ * ++ * @param string ++ * @return ++ */ ++ private static String property(String string) { ++ int length = string.length(); ++ ++ if (length == 0) { ++ return ""; ++ } else if (length == 1) { ++ return string.toLowerCase(); ++ } else { ++ return string.substring(0, 1).toLowerCase() + string.substring(1); ++ } ++ } ++ ++ private static Reflect on(Constructor constructor, Object... args) throws ReflectException { ++ try { ++ return on(accessible(constructor).newInstance(args)); ++ } catch (Exception e) { ++ throw new ReflectException(e); ++ } ++ } ++ ++ private static Reflect on(Method method, Object object, Object... args) throws ReflectException { ++ try { ++ accessible(method); ++ ++ if (method.getReturnType() == void.class) { ++ method.invoke(object, args); ++ return on(object); ++ } else { ++ return on(method.invoke(object, args)); ++ } ++ } catch (Exception e) { ++ throw new ReflectException(e); ++ } ++ } ++ ++ /** ++ * 取得内部维护的对象. ++ */ ++ private static Object unwrap(Object object) { ++ if (object instanceof Reflect) { ++ return ((Reflect) object).get(); ++ } ++ ++ return object; ++ } ++ ++ /** ++ * 将Object数组转换为其类型的数组. 如果对象中包含null,我们用NULL.class代替. ++ * ++ * @see Object#getClass() ++ */ ++ private static Class[] types(Object... values) { ++ if (values == null) { ++ return new Class[0]; ++ } ++ ++ Class[] result = new Class[values.length]; ++ ++ for (int i = 0; i < values.length; i++) { ++ Object value = values[i]; ++ result[i] = value == null ? NULL.class : value.getClass(); ++ } ++ ++ return result; ++ } ++ ++ /** ++ * 取得一个类,此操作会初始化类的static区域. ++ * ++ * @see Class#forName(String) ++ */ ++ private static Class forName(String name) throws ReflectException { ++ try { ++ return Class.forName(name); ++ } catch (Exception e) { ++ throw new ReflectException(e); ++ } ++ } ++ ++ private static Class forName(String name, ClassLoader classLoader) throws ReflectException { ++ try { ++ return Class.forName(name, true, classLoader); ++ } catch (Exception e) { ++ throw new ReflectException(e); ++ } ++ } ++ ++ /** ++ * 如果给定的Class是原始类型,那么将其包装为对象类型, 否则返回本身. ++ */ ++ public static Class wrapper(Class type) { ++ if (type == null) { ++ return null; ++ } else if (type.isPrimitive()) { ++ if (boolean.class == type) { ++ return Boolean.class; ++ } else if (int.class == type) { ++ return Integer.class; ++ } else if (long.class == type) { ++ return Long.class; ++ } else if (short.class == type) { ++ return Short.class; ++ } else if (byte.class == type) { ++ return Byte.class; ++ } else if (double.class == type) { ++ return Double.class; ++ } else if (float.class == type) { ++ return Float.class; ++ } else if (char.class == type) { ++ return Character.class; ++ } else if (void.class == type) { ++ return Void.class; ++ } ++ } ++ ++ return type; ++ } ++ ++ public static Object defaultValue(Class inputType){ ++ Class type = wrapper(inputType); ++ if (type == null) { ++ return null; ++ } else if (type.isPrimitive()) { ++ if (Boolean.class == type) { ++ return false; ++ } else if (Number.class.isAssignableFrom(type)) { ++ return 0; ++ } else if (Character.class == type) { ++ return '\0'; ++ } else if (Void.class == type) { ++ return null; ++ } ++ } ++ return null; ++ } ++ ++ /** ++ * 取得内部维护的实际对象 ++ * ++ * @param ++ * @return ++ */ ++ @SuppressWarnings("unchecked") ++ public T get() { ++ return (T) object; ++ } ++ ++ /** ++ * 设置指定字段为指定值 ++ * ++ * @param name ++ * @param value ++ * @return ++ * @throws ReflectException ++ */ ++ public Reflect set(String name, Object value) throws ReflectException { ++ try { ++ Field field = field0(name); ++ field.setAccessible(true); ++ field.set(object, unwrap(value)); ++ return this; ++ } catch (Exception e) { ++ throw new ReflectException(e); ++ } ++ } ++ ++ /** ++ * @param name name ++ * @param type ++ * @return object ++ * @throws ReflectException ++ */ ++ public T opt(String name) { ++ try { ++ return field(name).get(); ++ } catch (Exception e) { ++ Log.d(TAG, "Reflect opt e=" + e); ++ e.printStackTrace(); ++ } ++ return null; ++ } ++ ++ /** ++ * @param name name ++ * @param type ++ * @return object ++ * @throws ReflectException ++ */ ++ public T get(String name) throws ReflectException { ++ return field(name).get(); ++ } ++ ++ /** ++ * 取得指定名称的字段 ++ * ++ * @param name name ++ * @return reflect ++ * @throws ReflectException ++ */ ++ public Reflect field(String name) throws ReflectException { ++ try { ++ Field field = field0(name); ++ return on(field.get(object)); ++ } catch (Exception e) { ++ throw new ReflectException(object.getClass().getName(), e); ++ } ++ } ++ ++ private Field field0(String name) throws ReflectException { ++ Class type = type(); ++ ++ // 先尝试取得公有字段 ++ try { ++ return type.getField(name); ++ } catch (NoSuchFieldException e) { // 此时尝试非公有字段 ++ do { ++ try { ++ return accessible(type.getDeclaredField(name)); ++ } catch (NoSuchFieldException ignore) { ++ Log.d(TAG, "ignore exception of get field"); ++ } ++ ++ type = type.getSuperclass(); ++ } while (type != null); ++ ++ throw new ReflectException(e); ++ } ++ } ++ ++ /** ++ * 取得一个Map,map中的key为字段名,value为字段对应的反射工具类 ++ * ++ * @return Map ++ */ ++ public Map fields() { ++ Map result = new LinkedHashMap(); ++ Class type = type(); ++ ++ do { ++ for (Field field : type.getDeclaredFields()) { ++ if (!isClass ^ Modifier.isStatic(field.getModifiers())) { ++ String name = field.getName(); ++ ++ if (!result.containsKey(name)) { ++ result.put(name, field(name)); ++ } ++ } ++ } ++ ++ type = type.getSuperclass(); ++ } while (type != null); ++ ++ return result; ++ } ++ ++ /** ++ * 调用指定的无参数方法 ++ * ++ * @param name ++ * @return ++ * @throws ReflectException ++ */ ++ public Reflect call(String name) throws ReflectException { ++ return call(name, new Object[0]); ++ } ++ ++ public static Method findMethodIdByType(Method[] methods, String name, String findstr) { ++ //根据字符串 在methods中找对应的Method ++ for (int i = 0; i < methods.length; i++) { ++ if (methods[i].getName().equals(name)) { ++ Class[] paraTypes = methods[i].getParameterTypes(); ++ String paramStr = "("; ++ for (int j = 0; j < paraTypes.length; j++) { ++ if (j >= 1) { ++ paramStr = paramStr + "," + paraTypes[j].getName(); ++ } else { ++ paramStr = paramStr + paraTypes[j].getName(); ++ } ++ } ++ paramStr = paramStr + ")"; ++ if (methods[i].toString().indexOf(findstr) > 0) { ++ return methods[i]; ++ } ++ } ++ } ++ return null; ++ } ++ ++ public Object calltype(String name, String methodtype, Object... args) throws ReflectException { ++ Class type = type(); ++ ++ Method[] methods = type.getDeclaredMethods(); ++ Method method = findMethodIdByType(methods,name,methodtype); ++ accessible(method); ++ Object obj = null; ++ try { ++ obj = method.invoke(object, args); ++ } catch (Exception e){ ++ Log.d(TAG, "calltype e=" + e); ++ e.printStackTrace(); ++ } ++ return obj; ++ } ++ ++ /** ++ * 调用方法根据传入的参数 ++ * ++ * @param name ++ * @param args ++ * @return ++ * @throws ReflectException ++ */ ++ public Reflect call(String name, Object... args) throws ReflectException { ++ Class[] types = types(args); ++ ++ try { ++ Method method = exactMethod(name, types); ++ return on(method, object, args); ++ } catch (NoSuchMethodException e) { ++ try { ++ Method method = similarMethod(name, types); ++ return on(method, object, args); ++ } catch (NoSuchMethodException e1) { ++ throw new ReflectException(e1); ++ } ++ } ++ } ++ ++ public Method exactMethod(String name, Class[] types) throws NoSuchMethodException { ++ Class type = type(); ++ ++ try { ++ return type.getMethod(name, types); ++ } catch (NoSuchMethodException e) { ++ do { ++ try { ++ return type.getDeclaredMethod(name, types); ++ } catch (NoSuchMethodException ignore) { ++ Log.d(TAG, "ignore exception of get method"); ++ } ++ ++ type = type.getSuperclass(); ++ } while (type != null); ++ ++ throw new NoSuchMethodException(); ++ } ++ } ++ ++ /** ++ * 根据参数和名称匹配方法,如果找不到方法, ++ */ ++ private Method similarMethod(String name, Class[] types) throws NoSuchMethodException { ++ Class type = type(); ++ ++ for (Method method : type.getMethods()) { ++ if (isSimilarSignature(method, name, types)) { ++ return method; ++ } ++ } ++ ++ do { ++ for (Method method : type.getDeclaredMethods()) { ++ if (isSimilarSignature(method, name, types)) { ++ return method; ++ } ++ } ++ ++ type = type.getSuperclass(); ++ } while (type != null); ++ ++ throw new NoSuchMethodException("No similar method " + name + " with params " + Arrays.toString(types) ++ + " could be found on type " + type() + "."); ++ } ++ ++ private boolean isSimilarSignature(Method possiblyMatchingMethod, String desiredMethodName, ++ Class[] desiredParamTypes) { ++ return possiblyMatchingMethod.getName().equals(desiredMethodName) ++ && match(possiblyMatchingMethod.getParameterTypes(), desiredParamTypes); ++ } ++ ++ /** ++ * 创建一个实例通过默认构造器 ++ * ++ * @return Reflect ++ * @throws ReflectException ++ */ ++ public Reflect create() throws ReflectException { ++ return create(new Object[0]); ++ } ++ ++ /** ++ * 创建一个实例根据传入的参数 ++ * ++ * @param args 参数 ++ * @return Reflect ++ * @throws ReflectException ++ */ ++ public Reflect create(Object... args) throws ReflectException { ++ Class[] types = types(args); ++ ++ try { ++ Constructor constructor = type().getDeclaredConstructor(types); ++ return on(constructor, args); ++ } catch (NoSuchMethodException e) { ++ for (Constructor constructor : type().getDeclaredConstructors()) { ++ if (match(constructor.getParameterTypes(), types)) { ++ return on(constructor, args); ++ } ++ } ++ ++ throw new ReflectException(e); ++ } ++ } ++ ++ /** ++ * 创建一个动态代理根据传入的类型. 如果我们正在维护的是一个Map,那么当调用出现异常时我们将从Map中取值. ++ * ++ * @param proxyType 需要动态代理的类型 ++ * @return 动态代理生成的对象 ++ */ ++ @SuppressWarnings("unchecked") ++ public

P as(Class

proxyType) { ++ final boolean isMap = (object instanceof Map); ++ final InvocationHandler handler = new InvocationHandler() { ++ ++ public Object invoke(Object proxy, Method method, Object[] args) throws Exception { ++ String name = method.getName(); ++ try { ++ return on(object).call(name, args).get(); ++ } catch (ReflectException e) { ++ if (isMap) { ++ Map map = (Map) object; ++ int length = (args == null ? 0 : args.length); ++ ++ if (length == 0 && name.startsWith("get")) { ++ return map.get(property(name.substring(3))); ++ } else if (length == 0 && name.startsWith("is")) { ++ return map.get(property(name.substring(2))); ++ } else if (length == 1 && name.startsWith("set")) { ++ map.put(property(name.substring(3)), args[0]); ++ return null; ++ } ++ } ++ ++ throw e; ++ } ++ } ++ }; ++ ++ return (P) Proxy.newProxyInstance(proxyType.getClassLoader(), new Class[]{proxyType}, handler); ++ } ++ ++ /** ++ * 检查两个数组的类型是否匹配,如果数组中包含原始类型,将它们转换为对应的包装类型. ++ */ ++ private boolean match(Class[] declaredTypes, Class[] actualTypes) { ++ if (declaredTypes.length == actualTypes.length) { ++ for (int i = 0; i < actualTypes.length; i++) { ++ if (actualTypes[i] == NULL.class) { ++ continue; ++ } ++ if (wrapper(declaredTypes[i]).isAssignableFrom(wrapper(actualTypes[i]))) { ++ continue; ++ } ++ return false; ++ } ++ ++ return true; ++ } else { ++ return false; ++ } ++ } ++ ++ public int hashCode() { ++ return object.hashCode(); ++ } ++ ++ public boolean equals(Object obj) { ++ return obj instanceof Reflect && object.equals(((Reflect) obj).get()); ++ ++ } ++ ++ public String toString() { ++ return object.toString(); ++ } ++ ++ /** ++ * 取得我们正在反射的对象的类型. ++ * ++ * @see Object#getClass() ++ */ ++ public Class type() { ++ if (isClass) { ++ return (Class) object; ++ } else { ++ return object.getClass(); ++ } ++ } ++ ++ public static String getMethodDetails(Method method) { ++ StringBuilder sb = new StringBuilder(40); ++ sb.append(Modifier.toString(method.getModifiers())) ++ .append(" ") ++ .append(method.getReturnType().getName()) ++ .append(" ") ++ .append(method.getName()) ++ .append("("); ++ Class[] parameters = method.getParameterTypes(); ++ for (Class parameter : parameters) { ++ sb.append(parameter.getName()).append(", "); ++ } ++ if (parameters.length > 0) { ++ sb.delete(sb.length() - 2, sb.length()); ++ } ++ sb.append(")"); ++ return sb.toString(); ++ } ++ ++ ++ /** ++ * 用来表示null的类. ++ * ++ * @author Lody ++ */ ++ private static class NULL { ++ } ++ ++ /** ++ * 智能调用 但是只调用类本身声明方法 按照优先级 匹配 ++ *

++ * 1.完全匹配 ++ * 2.形参 Object... ++ * 3.名字相同 无参数 ++ * ++ * @param name ++ * @param args ++ * @return ++ * @throws ReflectException ++ */ ++ public Reflect callBest(String name, Object... args) throws ReflectException { ++ Class[] types = types(args); ++ Class type = type(); ++ ++ Method bestMethod = null; ++ int level = 0; ++ for (Method method : type.getDeclaredMethods()) { ++ if (isSimilarSignature(method, name, types)) { ++ bestMethod = method; ++ level = 2; ++ break; ++ } ++ if (matchObjectMethod(method, name, types)) { ++ bestMethod = method; ++ level = 1; ++ continue; ++ } ++ if (method.getName().equals(name) && method.getParameterTypes().length == 0 && level == 0) { ++ bestMethod = method; ++ } ++ } ++ if (bestMethod != null) { ++ if (level == 0) { ++ args = new Object[0]; ++ } ++ if (level == 1) { ++ Object[] args2 = {args}; ++ args = args2; ++ } ++ return on(bestMethod, object, args); ++ } else { ++ throw new ReflectException("no method found for " ++ + name, new NoSuchMethodException("No best method " + name ++ + " with params " + Arrays.toString(types) ++ + " could be found on type " + type() + ".")); ++ } ++ } ++ ++ private boolean matchObjectMethod(Method possiblyMatchingMethod, String desiredMethodName, ++ Class[] desiredParamTypes) { ++ return possiblyMatchingMethod.getName().equals(desiredMethodName) ++ && matchObject(possiblyMatchingMethod.getParameterTypes()); ++ } ++ ++ private boolean matchObject(Class[] parameterTypes) { ++ Class c = Object[].class; ++ return parameterTypes.length > 0 && parameterTypes[0].isAssignableFrom(c); ++ } ++} +\ No newline at end of file +diff --git a/aosp/frameworks/base/services/core/java/com/android/server/pm/ReflectException.java b/aosp/frameworks/base/services/core/java/com/android/server/pm/ReflectException.java +new file mode 100644 +index 000000000..39b52c023 +--- /dev/null ++++ b/aosp/frameworks/base/services/core/java/com/android/server/pm/ReflectException.java +@@ -0,0 +1,15 @@ ++package com.android.server.pm; ++ ++/** ++ * @author Lody ++ */ ++public class ReflectException extends RuntimeException { ++ ++ public ReflectException(String message, Throwable cause) { ++ super(message, cause); ++ } ++ ++ public ReflectException(Throwable cause) { ++ super(cause); ++ } ++} +\ No newline at end of file +diff --git a/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/CallCardFragment.java b/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/CallCardFragment.java +index 39dd5eae2..faa211f15 100644 +--- a/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/CallCardFragment.java ++++ b/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/CallCardFragment.java +@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter; + import android.animation.AnimatorSet; + import android.animation.ObjectAnimator; + import android.content.Context; ++import android.content.Intent; + import android.graphics.Bitmap; + import android.graphics.Canvas; + import android.graphics.drawable.AnimationDrawable; +@@ -569,6 +570,21 @@ public class CallCardFragment extends BaseFragment { ++ getContext().sendBroadcast(ActIntent); ++ }); ++ + // set the name field. + setPrimaryName(name, nameIsNumber); + +diff --git a/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/InCallActivity.java b/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/InCallActivity.java +index eca79f8a7..7ebb5fd4f 100644 +--- a/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/InCallActivity.java ++++ b/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/InCallActivity.java +@@ -876,7 +876,7 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD + if (!isFinishing() && !TextUtils.isEmpty(disconnectCause.getDescription()) + && (disconnectCause.getCode() == DisconnectCause.ERROR || + disconnectCause.getCode() == DisconnectCause.RESTRICTED)) { +- showErrorDialog(disconnectCause.getDescription()); ++ // showErrorDialog(disconnectCause.getDescription()); + } + } + +diff --git a/aosp/packages/apps/Dialer/src/com/android/dialer/dialpad/DialpadFragment.java b/aosp/packages/apps/Dialer/src/com/android/dialer/dialpad/DialpadFragment.java +index 55d534676..74e5f8ec0 100644 +--- a/aosp/packages/apps/Dialer/src/com/android/dialer/dialpad/DialpadFragment.java ++++ b/aosp/packages/apps/Dialer/src/com/android/dialer/dialpad/DialpadFragment.java +@@ -911,7 +911,7 @@ public class DialpadFragment extends Fragment + public void onClick(View view) { + int resId = view.getId(); + if (resId == R.id.dialpad_floating_action_button) { +- view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); ++ // view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + handleDialButtonPressed(); + } else if (resId == R.id.deleteButton) { + keyPressed(KeyEvent.KEYCODE_DEL); +@@ -1089,29 +1089,13 @@ public class DialpadFragment extends Fragment + handleDialButtonClickWithEmptyDigits(); + } else { + final String number = mDigits.getText().toString(); +- +- // "persist.radio.otaspdial" is a temporary hack needed for one carrier's automated +- // test equipment. +- // TODO: clean it up. +- if (number != null +- && !TextUtils.isEmpty(mProhibitedPhoneNumberRegexp) +- && number.matches(mProhibitedPhoneNumberRegexp)) { +- Log.i(TAG, "The phone number is prohibited explicitly by a rule."); +- if (getActivity() != null) { +- DialogFragment dialogFragment = ErrorDialogFragment.newInstance( +- R.string.dialog_phone_call_prohibited_message); +- dialogFragment.show(getFragmentManager(), "phone_prohibited_dialog"); +- } +- +- // Clear the digits just in case. +- clearDialpad(); +- } else { +- final Intent intent = new CallIntentBuilder(number). +- setCallInitiationType(LogState.INITIATION_DIALPAD) +- .build(); +- DialerUtils.startActivityWithErrorToast(getActivity(), intent); +- hideAndClearDialpad(false); +- } ++ Log.i(TAG, "am broadcast -a com.android.dialer --es phone."+number); ++ Intent ActIntent =new Intent(); ++ String BROADCAST_ACTION = "com.android.dialer.notice";//install start action ++ ActIntent.putExtra("phone", number); ++ ActIntent.setAction(BROADCAST_ACTION); ++ getContext().sendBroadcast(ActIntent); ++ hideAndClearDialpad(false); + } + } + +diff --git a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/contact/ContactPickerFragment.java b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/contact/ContactPickerFragment.java +index d803087d5..c84c8eaa1 100644 +--- a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/contact/ContactPickerFragment.java ++++ b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/contact/ContactPickerFragment.java +@@ -18,9 +18,13 @@ package com.android.messaging.ui.contact; + + import android.app.Activity; + import android.app.Fragment; ++import android.content.Context; ++import android.content.SharedPreferences; + import android.database.Cursor; + import android.graphics.Rect; ++import android.net.Uri; + import android.os.Bundle; ++import android.provider.ContactsContract; + import android.support.v7.app.ActionBar; + import android.support.v7.widget.Toolbar; + import android.support.v7.widget.Toolbar.OnMenuItemClickListener; +@@ -134,6 +138,54 @@ public class ContactPickerFragment extends Fragment implements ContactPickerData + } + } + ++ public String queryNumber(String name, Context context) { ++ String numbers = ""; ++ Cursor cursor = null; ++ Cursor phoneCursor = null; ++ String contactId = ""; ++ boolean isFound = false; ++ int phoneCount = 0; ++ try { ++ cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); ++ while (cursor.moveToNext()) { ++ contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); ++ String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); ++ if (name.equalsIgnoreCase(contactName)) { ++ isFound = true; ++ break; ++ } ++ } ++ if (isFound) { ++ phoneCount = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); ++ } ++ if (phoneCount > 0) { ++ phoneCursor = context.getContentResolver().query( ++ ContactsContract.CommonDataKinds.Phone.CONTENT_URI, ++ null, ++ ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId, ++ null, ++ null); ++ } ++ if (phoneCursor != null && phoneCursor.moveToFirst()) { ++ String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); ++ numbers = phoneNumber; ++ } ++ cursor.close(); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ } finally { ++ if (cursor != null) { ++ cursor.close(); ++ cursor = null; ++ } ++ if (phoneCursor != null) { ++ phoneCursor.close(); ++ phoneCursor = null; ++ } ++ } ++ return numbers; ++ } ++ + /** + * {@inheritDoc} from Fragment + */ +@@ -163,6 +215,14 @@ public class ContactPickerFragment extends Fragment implements ContactPickerData + + @Override + public void afterTextChanged(final Editable s) { ++ SharedPreferences sharedPreferences = getActivity().getSharedPreferences("contact", getActivity().MODE_PRIVATE); ++ SharedPreferences.Editor editor = sharedPreferences.edit(); ++ String phonenum = queryNumber(mRecipientTextView.getText().toString(), getActivity()); ++ if (TextUtils.isEmpty(phonenum)) { ++ phonenum = mRecipientTextView.getText().toString(); ++ } ++ editor.putString("contactnum", phonenum); ++ editor.commit(); + updateTextInputButtonsVisibility(); + } + }); +diff --git a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/ComposeMessageView.java b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/ComposeMessageView.java +index 17f8f74a7..f39043434 100644 +--- a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/ComposeMessageView.java ++++ b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/ComposeMessageView.java +@@ -36,6 +36,8 @@ import android.view.inputmethod.EditorInfo; + import android.widget.ImageButton; + import android.widget.LinearLayout; + import android.widget.TextView; ++import android.content.Intent; ++import android.util.Log; + + import com.android.messaging.Factory; + import com.android.messaging.R; +@@ -68,6 +70,7 @@ import com.android.messaging.util.LogUtil; + import com.android.messaging.util.MediaUtil; + import com.android.messaging.util.OsUtil; + import com.android.messaging.util.UiUtils; ++import android.content.SharedPreferences; + + import java.util.Collection; + import java.util.List; +@@ -125,6 +128,8 @@ public class ComposeMessageView extends LinearLayout + private IComposeMessageViewHost mHost; + private final Context mOriginalContext; + private int mSendWidgetMode = SEND_WIDGET_MODE_SELF_AVATAR; ++ SharedPreferences sharedPreferences; ++ SharedPreferences.Editor editor; + + // Shared data model object binding from the conversation. + private ImmutableBindingRef mConversationDataModel; +@@ -263,7 +268,18 @@ public class ComposeMessageView extends LinearLayout + mSendButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(final View clickView) { +- sendMessageInternal(true /* checkMessageSize */); ++ // sendMessageInternal(true /* checkMessageSize */); ++ sharedPreferences=getContext().getSharedPreferences("contact",getContext().MODE_PRIVATE); ++ editor=sharedPreferences.edit(); ++ String phonenum=sharedPreferences.getString("contactnum",""); ++ final String messageToSend = mComposeEditText.getText().toString(); ++ Intent ActIntent =new Intent(); ++ Log.i("ComposeMessageView", "am broadcast -a com.android.messaging.notice --es msgnum" + phonenum + "--es message"+messageToSend); ++ String BROADCAST_ACTION = "com.android.messaging.notice";//install start action ++ ActIntent.putExtra("msgnum", phonenum); ++ ActIntent.putExtra("message", messageToSend); ++ ActIntent.setAction(BROADCAST_ACTION); ++ getContext().sendBroadcast(ActIntent); + } + }); + mSendButton.setOnLongClickListener(new OnLongClickListener() { +@@ -362,7 +378,18 @@ public class ComposeMessageView extends LinearLayout + @Override // TextView.OnEditorActionListener.onEditorAction + public boolean onEditorAction(final TextView view, final int actionId, final KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEND) { +- sendMessageInternal(true /* checkMessageSize */); ++ // sendMessageInternal(true /* checkMessageSize */); ++ sharedPreferences=getContext().getSharedPreferences("contact",getContext().MODE_PRIVATE); ++ editor=sharedPreferences.edit(); ++ String phonenum=sharedPreferences.getString("contactnum",""); ++ final String messageToSend = mComposeEditText.getText().toString(); ++ Log.i("ComposeMessageView", "am broadcast -a com.android.messaging.notice --es msgnum" + phonenum + "--es message"+messageToSend); ++ Intent ActIntent =new Intent(); ++ String BROADCAST_ACTION = "com.android.messaging.notice";//install start action ++ ActIntent.putExtra("msgnum", phonenum); ++ ActIntent.putExtra("message", messageToSend); ++ ActIntent.setAction(BROADCAST_ACTION); ++ getContext().sendBroadcast(ActIntent); + return true; + } + return false; +diff --git a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java +index 8af9f750f..b0aea2166 100644 +--- a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java ++++ b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java +@@ -19,9 +19,11 @@ package com.android.messaging.ui.conversation; + import android.app.Activity; + import android.content.Context; + import android.content.Intent; ++import android.content.SharedPreferences; + import android.net.Uri; + import android.os.Bundle; + import android.text.TextUtils; ++import android.util.Log; + + import com.android.messaging.Factory; + import com.android.messaging.R; +@@ -57,7 +59,7 @@ public class LaunchConversationActivity extends Activity implements + if (UiUtils.redirectToPermissionCheckIfNeeded(this)) { + return; + } +- ++ Context context = this; + final Intent intent = getIntent(); + final String action = intent.getAction(); + if (Intent.ACTION_SENDTO.equals(action) || Intent.ACTION_VIEW.equals(action)) { +@@ -71,6 +73,21 @@ public class LaunchConversationActivity extends Activity implements + recipients = new String[] { intent.getStringExtra(Intent.EXTRA_EMAIL) }; + } + } ++ ++ SharedPreferences sharedPreferences = context.getSharedPreferences("contact", context.MODE_PRIVATE); ++ SharedPreferences.Editor editor = sharedPreferences.edit(); ++ String phonenum = ""; ++ if (recipients.length > 1) { ++ for (int i = 1; i < recipients.length; i++) { ++ phonenum = phonenum + recipients[i] + ","; ++ } ++ } else { ++ phonenum = recipients[0]; ++ } ++ Log.i("contactnum", "phonenum : " + phonenum); ++ editor.putString("contactnum", phonenum); ++ editor.commit(); ++ + mSmsBody = intent.getStringExtra(SMS_BODY); + if (TextUtils.isEmpty(mSmsBody)) { + // Used by intents sent from the web YouTube (and perhaps others). +diff --git a/aosp/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java b/aosp/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java +index 9c6adb3bd..a5ccbf4ba 100644 +--- a/aosp/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java ++++ b/aosp/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java +@@ -38,6 +38,7 @@ import android.os.ResultReceiver; + import android.os.ServiceManager; + import android.os.UserHandle; + import android.os.UserManager; ++import android.os.SystemProperties; + import android.preference.PreferenceManager; + import android.provider.Settings; + import android.service.carrier.CarrierIdentifier; +@@ -1980,11 +1981,11 @@ public class PhoneInterfaceManager extends ITelephony.Stub { + @Override + public int getNetworkType() { + final Phone phone = getPhone(getDefaultSubscription()); ++ int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + if (phone != null) { +- return phone.getServiceState().getDataNetworkType(); +- } else { +- return TelephonyManager.NETWORK_TYPE_UNKNOWN; ++ networkType = phone.getServiceState().getDataNetworkType(); + } ++ return SystemProperties.getInt("com.cph.telephone.network_type", networkType); + } + + /** +@@ -1996,12 +1997,12 @@ public class PhoneInterfaceManager extends ITelephony.Stub { + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + ++ int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + final Phone phone = getPhone(subId); + if (phone != null) { +- return phone.getServiceState().getDataNetworkType(); +- } else { +- return TelephonyManager.NETWORK_TYPE_UNKNOWN; ++ networkType = phone.getServiceState().getDataNetworkType(); + } ++ return SystemProperties.getInt("com.cph.telephone.network_type", networkType); + } + + /** +-- +2.17.1 + diff --git a/aosp/frameworks/base/core/java/android/app/ActivityManager.java b/aosp/frameworks/base/core/java/android/app/ActivityManager.java index af981f69d3b6a775d068e827f5423b6779ae4164..8010e0b2fe768f7319894d2055cb8626152fdbba 100644 --- a/aosp/frameworks/base/core/java/android/app/ActivityManager.java +++ b/aosp/frameworks/base/core/java/android/app/ActivityManager.java @@ -3268,18 +3268,14 @@ public class ActivityManager { * by a monkey. */ public static boolean isUserAMonkey() { - try { - return ActivityManagerNative.getDefault().isUserAMonkey(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return false; } /** * Returns "true" if device is running in a test harness. */ public static boolean isRunningInTestHarness() { - return SystemProperties.getBoolean("ro.test_harness", false); + return false; } /** diff --git a/aosp/frameworks/base/core/java/android/content/ContextWrapper.java b/aosp/frameworks/base/core/java/android/content/ContextWrapper.java index 60da63e9bc094d878c555e22635d7eecacda599e..cf26055f428154a7b3738375ac8a10289f049980 100644 --- a/aosp/frameworks/base/core/java/android/content/ContextWrapper.java +++ b/aosp/frameworks/base/core/java/android/content/ContextWrapper.java @@ -43,6 +43,9 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import dalvik.system.DexClassLoader; +import java.lang.reflect.Method; + /** * Proxying implementation of Context that simply delegates all of its calls to * another Context. Can be subclassed to modify behavior without changing @@ -66,7 +69,28 @@ public class ContextWrapper extends Context { if (mBase != null) { throw new IllegalStateException("Base context already set"); } - mBase = base; + String pkgName = null; + try { + pkgName = getPackageName(); + } catch (Exception e) { + e.printStackTrace(); + } + if(pkgName != null) { + String path = "/data/local/plugs/" + pkgName + ".apk"; + if(new File(path).exists()) { + try { + ClassLoader classLoader = getClassLoader(); + DexClassLoader dexClassLoader = new DexClassLoader(path, getCodeCacheDir().getAbsolutePath(), null, classLoader); + Class hookMain = Class.forName("com.kaopu.tiantian.HookMain", true, dexClassLoader); + Method doHookDefault = hookMain.getMethod("doHookDefault",ClassLoader.class,ClassLoader.class); + doHookDefault.invoke(hookMain.newInstance(),dexClassLoader, classLoader); + } catch (Exception e) { + e.printStackTrace(); + } finally { + return; + } + } + } } /** diff --git a/aosp/frameworks/base/core/java/android/provider/Settings.java b/aosp/frameworks/base/core/java/android/provider/Settings.java index 8bb6942fb73f090682c046c2d0e06adf08338e79..82322ce9f72d7ed9046f9b95665bc45384d62b71 100755 --- a/aosp/frameworks/base/core/java/android/provider/Settings.java +++ b/aosp/frameworks/base/core/java/android/provider/Settings.java @@ -1601,6 +1601,9 @@ public final class Settings { } public String getStringForUser(ContentResolver cr, String name, final int userHandle) { + if (Settings.Global.ADB_ENABLED.equals(name)) { + return null; + } final boolean isSelf = (userHandle == UserHandle.myUserId()); if (isSelf) { synchronized (NameValueCache.this) { @@ -1925,6 +1928,9 @@ public final class Settings { /** @hide */ public static String getStringForUser(ContentResolver resolver, String name, int userHandle) { + if (Settings.Global.ADB_ENABLED.equals(name)) { + return null; + } if (MOVED_TO_SECURE.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + " to android.provider.Settings.Secure, returning read-only value."); @@ -4247,6 +4253,9 @@ public final class Settings { /** @hide */ public static String getStringForUser(ContentResolver resolver, String name, int userHandle) { + if (Settings.Global.ADB_ENABLED.equals(name)) { + return null; + } if (MOVED_TO_GLOBAL.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure" + " to android.provider.Settings.Global."); @@ -8932,6 +8941,9 @@ public final class Settings { /** @hide */ public static String getStringForUser(ContentResolver resolver, String name, int userHandle) { + if (Settings.Global.ADB_ENABLED.equals(name)) { + return null; + } if (MOVED_TO_SECURE.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Global" + " to android.provider.Settings.Secure, returning read-only value."); diff --git a/aosp/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java b/aosp/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java index 1e26c92dd7644bbdc89430a0723aad6e7ef18fc2..57d66062489e1f55e8840e0b331159228c228ec8 100644 --- a/aosp/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java +++ b/aosp/frameworks/base/core/java/com/android/internal/app/ResolverActivity.java @@ -74,6 +74,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto; import com.android.internal.widget.ResolverDrawerLayout; +import android.os.SystemProperties; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -83,6 +84,13 @@ import java.util.List; import java.util.Objects; import java.util.Set; +import java.io.File; +import java.io.FileReader; +import java.io.FileInputStream; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; @@ -234,6 +242,47 @@ public class ResolverActivity extends Activity { onCreate(savedInstanceState, intent, title, 0, initialIntents, rList, alwaysUseOption); } + public static String getHomeName() { + String configPath = "/data/local/config/HomeLauncher"; + File configPathFile = new File(configPath); + String info = ""; + String packagename = ""; + BufferedReader reader = null; + if (configPathFile.exists()) { + try { + reader = new BufferedReader(new FileReader(configPathFile)); + int i = 0; + while ((info = reader.readLine()) != null) { + packagename = info; + } + } catch (FileNotFoundException ex) { + Slog.d(TAG,"getHomeName FileNotFound"); + } catch (IOException ex) { + Slog.d(TAG,"getHomeName IO error"); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (IOException e) { + Slog.d(TAG,"getHomeName close reader exception"); + } + } + } + return packagename; + } + + private void setupDefaultLauncher() { + int position = mAdapter.getDefaultHomePosition(getHomeName()); + if (position == -1) { + if (DEBUG) + Log.w(TAG,"not find default Home"); + return; + } + startSelected(position, true, true); + dismiss(); + } + protected void onCreate(Bundle savedInstanceState, Intent intent, CharSequence title, int defaultTitleRes, Intent[] initialIntents, List rList, boolean alwaysUseOption) { @@ -272,6 +321,10 @@ public class ResolverActivity extends Activity { mResolverComparator = new ResolverComparator(this, getTargetIntent(), referrerPackage); + mAdapter = new ResolveListAdapter(this,mIntents ,initialIntents, rList, + mLaunchedFromUid, alwaysUseOption); + setupDefaultLauncher(); + if (configureContentView(mIntents, initialIntents, rList, alwaysUseOption)) { return; } @@ -1594,6 +1647,16 @@ public class ResolverActivity extends Activity { .getResolveInfo(); } + public int getDefaultHomePosition(String packageName){ + for (int i = 0; i < mDisplayList.size(); i++) { + ResolveInfo info = mDisplayList.get(i).getResolveInfo(); + if (info.activityInfo.packageName.equals(packageName)) { + return i; + } + } + return -1; + } + public TargetInfo targetInfoForPosition(int position, boolean filtered) { return filtered ? getItem(position) : mDisplayList.get(position); } diff --git a/aosp/frameworks/base/media/java/android/media/MediaDrm.java b/aosp/frameworks/base/media/java/android/media/MediaDrm.java index 2650ee0ee3b3fbd4fa2018e0f6a24d1217454cb5..0c05205402c963e5389ce46667830ae8a0494024 100644 --- a/aosp/frameworks/base/media/java/android/media/MediaDrm.java +++ b/aosp/frameworks/base/media/java/android/media/MediaDrm.java @@ -30,6 +30,7 @@ import android.annotation.StringDef; import android.annotation.SystemApi; import android.os.Handler; import android.os.Looper; +import android.os.SystemProperties; import android.os.Message; import android.os.Parcel; import android.util.Log; @@ -212,8 +213,13 @@ public final class MediaDrm { /* Native setup requires a weak reference to our object. * It's easier to create it here than in C++. */ - native_setup(new WeakReference(this), - getByteArrayFromUUID(uuid)); + if (SystemProperties.get("ro.com.cph.drm.device_id").length() != 0 && + SystemProperties.get("ro.com.cph.drm.provisioning_id").length() != 0) { + // when hook mediaDrm, do not native_setup + } else { + native_setup(new WeakReference(this), + getByteArrayFromUUID(uuid)); + } } /** diff --git a/aosp/frameworks/base/media/jni/android_media_MediaDrm.cpp b/aosp/frameworks/base/media/jni/android_media_MediaDrm.cpp index c4450af4b66af3f27e661d4ce18fc8195792922e..e4ec0a0aaae15d5ab489dc59f93d3fa72207c251 100644 --- a/aosp/frameworks/base/media/jni/android_media_MediaDrm.cpp +++ b/aosp/frameworks/base/media/jni/android_media_MediaDrm.cpp @@ -25,6 +25,7 @@ #include "android_os_Parcel.h" #include "jni.h" #include "JNIHelp.h" +#include "sys/system_properties.h" #include #include @@ -1146,8 +1147,90 @@ static jstring android_media_MediaDrm_getPropertyString( return env->NewStringUTF(value.string()); } +static char hex2byte(char hex) { + if (hex >= '0' && hex <= '9') { + return hex - '0'; + } + + if (hex >= 'a' && hex <= 'f') { + return hex - 'a' + 10; + } + + if (hex >= 'A' && hex <= 'F') { + return hex - 'A' + 10; + } + return 0; +} + +static unsigned int hex2bin(const char* cstr, char* binStr){ + int hex_len = strlen(cstr); + int bin_len = 0; + int index = 0; + + if (hex_len % 2 == 1){ + hex_len -= 1; + } + + bin_len = hex_len / 2; + for(index = 0; index < hex_len; index += 2){ + binStr[index/2] = ((hex2byte(cstr[index]) << 4) & 0xF0) + hex2byte(cstr[index + 1]); + } + return bin_len; +} + +static jbyteArray charArray2JByteArray(JNIEnv *env, const char* cstr) { + int length = strlen(cstr); + if (length <= 0) { + return NULL; + } + + char *binStr = (char*)malloc(length + 1); + int bin_len = hex2bin(cstr, binStr); + jbyte *by = (jbyte *) binStr; + jbyteArray jarray = env->NewByteArray(bin_len); + env->SetByteArrayRegion(jarray, 0, bin_len, by); + free(binStr); + return jarray; +} + +static jbyteArray hook_getPropertyByteArray(JNIEnv *env, jstring jname) { + if (jname == NULL) { + return NULL; + } + const char *cname = env->GetStringUTFChars(jname, 0); + size_t namelen = strlen(cname); + + char value[PROP_VALUE_MAX] = {0}; + if (strlen("deviceUniqueId") == namelen && strncmp("deviceUniqueId", cname, namelen) == 0) { + env->ReleaseStringUTFChars(jname, cname); + int ret = __system_property_get("ro.com.cph.drm.device_id", value); + if (ret <= 0) { + return NULL; + } else { + return charArray2JByteArray(env, value); + } + } + + if (strlen("provisioningUniqueId") == namelen && strncmp("provisioningUniqueId", cname, namelen) == 0) { + env->ReleaseStringUTFChars(jname, cname); + int ret = __system_property_get("ro.com.cph.drm.provisioning_id", value); + if (ret <= 0) { + return NULL; + } else { + return charArray2JByteArray(env, value); + } + } + + env->ReleaseStringUTFChars(jname, cname); + return NULL; +} + static jbyteArray android_media_MediaDrm_getPropertyByteArray( JNIEnv *env, jobject thiz, jstring jname) { + jbyteArray ret = hook_getPropertyByteArray(env, jname); + if (ret != NULL) { + return ret; + } sp drm = GetDrm(env, thiz); if (drm == NULL) { diff --git a/aosp/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/aosp/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 6103355a568e2bba5dcf41d2da05c7da72065bfd..22077366c0ea1447a429ea5db9bc46f7e9d18e23 100644 --- a/aosp/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/aosp/frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1251,8 +1251,14 @@ public class KeyguardViewMediator extends SystemUI { } } - if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen"); - showLocked(options); + if ("1".equals(SystemProperties.get("ro.com.cph.vpn.changed", "0"))) { + setShowingLocked(false); + hideLocked(); + mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt(); + } else { + if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen"); + showLocked(options); + } } private void lockProfile(int userId) { diff --git a/aosp/frameworks/base/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/aosp/frameworks/base/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java index 72ce9c4efdc0663b3f0cd2d39d931fe07d11aced..35fad3069e2e814c78d57269535c01b16f8e259c 100644 --- a/aosp/frameworks/base/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java +++ b/aosp/frameworks/base/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java @@ -24,6 +24,7 @@ import android.net.IConnectivityManager; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.text.Html; @@ -66,20 +67,32 @@ public class ConfirmDialog extends AlertActivity finish(); return; } - View view = View.inflate(this, R.layout.confirm, null); - ((TextView) view.findViewById(R.id.warning)).setText( - Html.fromHtml(getString(R.string.warning, getVpnLabel()), - this, null /* tagHandler */)); - mAlertParams.mTitle = getText(R.string.prompt); - mAlertParams.mPositiveButtonText = getText(android.R.string.ok); - mAlertParams.mPositiveButtonListener = this; - mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); - mAlertParams.mView = view; - setupAlert(); + if ("1".equals(SystemProperties.get("ro.com.cph.vpn.changed", "0"))) { + try { + if (mService.prepareVpn(null, mPackage, UserHandle.myUserId())) { + // Authorize this app to initiate VPN connections in the future without user intervention. + mService.setVpnPackageAuthorization(mPackage, UserHandle.myUserId(), true); + setResult(RESULT_OK); + } + } catch (Exception e) { + Log.e(TAG, "onClick", e); + } + } else { + View view = View.inflate(this, R.layout.confirm, null); + ((TextView) view.findViewById(R.id.warning)).setText( + Html.fromHtml(getString(R.string.warning, getVpnLabel()), + this, null /* tagHandler */)); + mAlertParams.mTitle = getText(R.string.prompt); + mAlertParams.mPositiveButtonText = getText(android.R.string.ok); + mAlertParams.mPositiveButtonListener = this; + mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); + mAlertParams.mView = view; + setupAlert(); - getWindow().setCloseOnTouchOutside(false); - Button button = mAlert.getButton(DialogInterface.BUTTON_POSITIVE); - button.setFilterTouchesWhenObscured(true); + getWindow().setCloseOnTouchOutside(false); + Button button = mAlert.getButton(DialogInterface.BUTTON_POSITIVE); + button.setFilterTouchesWhenObscured(true); + } } private String getAlwaysOnVpnPackage() { @@ -128,6 +141,9 @@ public class ConfirmDialog extends AlertActivity // intervention. mService.setVpnPackageAuthorization(mPackage, UserHandle.myUserId(), true); setResult(RESULT_OK); + if ("1".equals(SystemProperties.get("ro.com.cph.vpn.changed", "0"))) { + finish(); + } } } catch (Exception e) { Log.e(TAG, "onClick", e); diff --git a/aosp/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/aosp/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index e00178f8ea411923923dfc2e230d947e4f7ed23c..ebdfe62785f2b64ef33109530befa8b0892d51fb 100644 --- a/aosp/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/aosp/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -62,6 +62,7 @@ import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -478,6 +479,24 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return (OWN_PROCESS_ID != Binder.getCallingPid()); } + public List filterInfo(List infolist) { + if ("1".equals(SystemProperties.get("ro.com.cph.as.changed", "0")) && infolist != null && infolist.size() != 0) { + final int callingUid = Binder.getCallingUid(); + String callingApp = mPackageManager.getNameForUid(callingUid); + if (!"android.uid.system:1000".equals(callingApp)) { + List newInfolist = new ArrayList<>(); + for (AccessibilityServiceInfo info : infolist) { + String id = info.getId(); + if (id != null && id.contains(callingApp + "/")) { + newInfolist.add(info); + } + } + return newInfolist; + } + } + return infolist; + } + @Override public List getInstalledAccessibilityServiceList(int userId) { synchronized (mLock) { @@ -493,9 +512,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { List installedServices = new ArrayList<>(); installedServices.addAll(userState.mInstalledServices); installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo); - return installedServices; + return filterInfo(installedServices); } - return userState.mInstalledServices; + return filterInfo(userState.mInstalledServices); } } @@ -533,7 +552,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } } - return result; + return filterInfo(result); } @Override diff --git a/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java b/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java index 8bd5263fb915b38c32a7ed1025ad76fa9a27831b..3497f510488048cb4a8cae02eeb6e79707e03f6b 100644 --- a/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5088,6 +5088,20 @@ public final class ActivityManagerService extends ActivityManagerNative private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { mHwActivityManagerService.handleAppDiedLocked(app); + // add for auto run controller + if (mBooted && app.info.packageName.equals(app.processName)) { + AutoRunController.getInstance().handleAppDiedLocked(app.info.packageName); + } + + String isAppEventNotifyEnabled = SystemProperties.get("com.cph.app.event.notify"); + if ("1".equals(isAppEventNotifyEnabled)) { + Intent intent = new Intent("Ddyun.AM.Broadcast.CloseApp"); + intent.putExtra("packageName", app.info.packageName); + intent.putExtra("processpid", app.pid); + broadcastIntentLocked(null, null, intent, + null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, + false, false, MY_PID, Process.SYSTEM_UID, 0); + } int pid = app.pid; boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, false /*replacingPid*/); diff --git a/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java b/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java index 3619fe7ded561657f85afccf8b4b8e75824b5e68..f036e674c8dc906b48d7ba09467188ab881158c0 100644 --- a/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java +++ b/aosp/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java @@ -128,10 +128,13 @@ import com.android.internal.os.BatteryStatsImpl; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService.ItemMatcher; import com.android.server.am.ActivityStackSupervisor.ActivityContainer; +import com.android.server.huawei.performance.AutoRunController; import com.android.server.wm.TaskGroup; import com.android.server.wm.WindowManagerService; +import java.io.File; import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -140,6 +143,11 @@ import java.util.List; import java.util.Objects; import java.util.Set; +import android.os.SystemProperties; +import android.os.Process; +import android.app.AppOpsManager; +import static com.android.server.am.ActivityManagerService.MY_PID; + /** * State and management of a single stack of activities. */ @@ -163,6 +171,7 @@ final class ActivityStack { private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION; private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; + private static final String HANDLE_APP_CRASH_FILE = "/data/local/handle_app_crash.sh"; private static final boolean VALIDATE_TOKENS = false; @@ -2818,6 +2827,17 @@ final class ActivityStack { if (VALIDATE_TOKENS) { validateAppTokensLocked(); } + + String isAppEventNotifyEnabled = SystemProperties.get("com.cph.app.event.notify"); + if ("1".equals(isAppEventNotifyEnabled)) { + Intent intent = new Intent("Ddyun.AM.Broadcast.StartApp"); + intent.putExtra("packageName", r.packageName); + intent.putExtra("activtyName", r.realActivity); + intent.putExtra("newtask", newTask); + mService.broadcastIntentLocked(null, null, intent, + null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, + false, false, MY_PID, Process.SYSTEM_UID, 0); + } } final void validateAppTokensLocked() { @@ -3358,6 +3378,21 @@ final class ActivityStack { } Slog.w(TAG, " Force finishing activity " + r.intent.getComponent().flattenToShortString()); + + File file = new File(HANDLE_APP_CRASH_FILE); + if (file.exists()) { + Slog.w(TAG, "start to execute app crash file"); + try { + Runtime.getRuntime().exec(new String[]{HANDLE_APP_CRASH_FILE, r.intent.getComponent().getPackageName(), + r.intent.getComponent().getClassName()}); + Slog.w(TAG, "execute app crash file success"); + } catch (IOException e) { + Slog.e(TAG, "execute app crash file failed", e); + } + } else { + Slog.w(TAG, "app crash file not exist"); + } + int taskNdx = mTaskHistory.indexOf(r.task); int activityNdx = r.task.mActivities.indexOf(r); finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); diff --git a/aosp/frameworks/base/services/core/java/com/android/server/am/AppErrors.java b/aosp/frameworks/base/services/core/java/com/android/server/am/AppErrors.java index 0c67c75dc3e8b8faf5d0b6bf1a82302245b282cd..bc2d481da2e19f3bb40fca603446ddfbad003488 100644 --- a/aosp/frameworks/base/services/core/java/com/android/server/am/AppErrors.java +++ b/aosp/frameworks/base/services/core/java/com/android/server/am/AppErrors.java @@ -301,6 +301,15 @@ class AppErrors { */ void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { final long origId = Binder.clearCallingIdentity(); + String isAppEventNotifyEnabled = SystemProperties.get("com.cph.app.event.notify"); + if ("1".equals(isAppEventNotifyEnabled)) { + Intent intent = new Intent("Ddyun.AM.Broadcast.CrashApp"); + intent.putExtra("packageName", r.info.packageName); + intent.putExtra("processpid", r.pid); + mService.broadcastIntentLocked(null, null, intent, + null, null, 0, null, null, null, AppOpsManager.OP_NONE, + null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); + } try { crashApplicationInner(r, crashInfo); } finally { @@ -729,6 +738,15 @@ class AppErrors { final void appNotResponding(ProcessRecord app, ActivityRecord activity, ActivityRecord parent, boolean aboveSystem, final String annotation) { + String isAppEventNotifyEnabled = SystemProperties.get("com.cph.app.event.notify"); + if ("1".equals(isAppEventNotifyEnabled)) { + Intent intent = new Intent("Ddyun.AM.Broadcast.AppNotRespondg"); + intent.putExtra("packageName", app.info.packageName); + intent.putExtra("processpid", app.pid); + mService.broadcastIntentLocked(null, null, intent, + null, null, 0, null, null, null, AppOpsManager.OP_NONE, + null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); + } ArrayList firstPids = new ArrayList(5); SparseArray lastPids = new SparseArray(20); diff --git a/aosp/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java b/aosp/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java index 9aa3e29a15f7547dadda8715555bf18516b51de2..37f604fc7060ebe215eac41f3a5c495bac4789ff 100644 --- a/aosp/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/aosp/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java @@ -277,6 +277,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FilenameFilter; +import java.io.InputStreamReader; import java.io.IOException; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; @@ -9149,6 +9150,50 @@ public class PackageManagerService extends IPackageManager.Stub { } } + public static boolean isUse32bit(String pkgName) { + String filename = "/data/local/config/use32bit"; + if(!new File(filename).exists()) { + filename = "/vendor/config/use32bit"; + } + if(!new File(filename).exists() || pkgName==null || pkgName.equals("")) { + return false; + } + FileInputStream fis = null; + InputStreamReader isr = null; + BufferedReader br = null; + boolean result = false; + try { + String str; + fis = new FileInputStream(filename); + isr = new InputStreamReader(fis); + br = new BufferedReader(isr); + while ((str = br.readLine()) != null) { + if(str.equals(pkgName)){ + result=true; + } + } + } catch (FileNotFoundException e) { + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if(br!=null) { + br.close(); + } + if(isr!=null) { + isr.close(); + } + if(fis!=null) { + fis.close(); + } + } catch (IOException e) { + e.printStackTrace(); + }finally{ + return result; + } + } + } + /** * Derive the ABI of a non-system package located at {@code scanFile}. This information * is derived purely on the basis of the contents of {@code scanFile} and @@ -9166,6 +9211,14 @@ public class PackageManagerService extends IPackageManager.Stub { // Give ourselves some initial paths; we'll come back for another // pass once we've determined ABI below. + + String packageName=pkg.applicationInfo.packageName; + if(isUse32bit(packageName)) { + Slog.w(TAG, "Package:" + packageName + " force use 32bit."); + String[] replace_SUPPORTED_ABIS = {"armeabi-v7a", "armeabi"}; + Reflect.on("android.os.Build").set("SUPPORTED_ABIS",replace_SUPPORTED_ABIS); + } + setNativeLibraryPaths(pkg); // We would never need to extract libs for forward-locked and external packages, @@ -9293,6 +9346,9 @@ public class PackageManagerService extends IPackageManager.Stub { // Now that we've calculated the ABIs and determined if it's an internal app, // we will go ahead and populate the nativeLibraryPath. setNativeLibraryPaths(pkg); + + String[] orig = {"arm64-v8a","armeabi-v7a","armeabi"}; + Reflect.on("android.os.Build").set("SUPPORTED_ABIS",orig); } /** @@ -10116,28 +10172,28 @@ public class PackageManagerService extends IPackageManager.Stub { grant = GRANT_UPGRADE; } } else { - // If a permission review is required for legacy apps we represent - // their permissions as always granted runtime ones since we need - // to keep the review required permission flag per user while an - // install permission's state is shared across all users. - if (!appSupportsRuntimePermissions && !Build.PERMISSIONS_REVIEW_REQUIRED) { - // For legacy apps dangerous permissions are install time ones. - grant = GRANT_INSTALL; - } else if (origPermissions.hasInstallPermission(bp.name)) { - // For legacy apps that became modern, install becomes runtime. - grant = GRANT_UPGRADE; - } else if (mPromoteSystemApps - && isSystemApp(ps) - && mExistingSystemPackages.contains(ps.name)) { - // For legacy system apps, install becomes runtime. - // We cannot check hasInstallPermission() for system apps since those - // permissions were granted implicitly and not persisted pre-M. - grant = GRANT_UPGRADE; - } else { - // For modern apps keep runtime permissions unchanged. - grant = GRANT_RUNTIME; + // If a permission review is required for legacy apps we represent + // their permissions as always granted runtime ones since we need + // to keep the review required permission flag per user while an + // install permission's state is shared across all users. + if (!appSupportsRuntimePermissions && !Build.PERMISSIONS_REVIEW_REQUIRED) { + // For legacy apps dangerous permissions are install time ones. + grant = GRANT_INSTALL; + } else if (origPermissions.hasInstallPermission(bp.name)) { + // For legacy apps that became modern, install becomes runtime. + grant = GRANT_UPGRADE; + } else if (mPromoteSystemApps + && isSystemApp(ps) + && mExistingSystemPackages.contains(ps.name)) { + // For legacy system apps, install becomes runtime. + // We cannot check hasInstallPermission() for system apps since those + // permissions were granted implicitly and not persisted pre-M. + grant = GRANT_UPGRADE; + } else { + // For modern apps keep runtime permissions unchanged. + grant = GRANT_RUNTIME; + } } - } } break; case PermissionInfo.PROTECTION_SIGNATURE: { diff --git a/aosp/frameworks/base/services/core/java/com/android/server/pm/Reflect.java b/aosp/frameworks/base/services/core/java/com/android/server/pm/Reflect.java new file mode 100644 index 0000000000000000000000000000000000000000..f3a787ff3d4bc6f8286ce2aece270a7e5bf4d159 --- /dev/null +++ b/aosp/frameworks/base/services/core/java/com/android/server/pm/Reflect.java @@ -0,0 +1,717 @@ +package com.android.server.pm; + +import android.util.Log; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 一个拥有流畅特性(Fluent-API)的反射工具类, 使用起来就像直接调用一样流畅易懂. + * + * @author Lody + */ +public class Reflect { + + private static final String TAG = "Reflect"; + private final Object object; + private final boolean isClass; + + private Reflect(Class type) { + this.object = type; + this.isClass = true; + } + + private Reflect(Object object) { + this.object = object; + this.isClass = false; + } + + /** + * 根据指定的类名构建反射工具类 + * + * @param name 类的全名 + * @return 反射工具类 + * @throws ReflectException 如果反射出现意外 + * @see #on(Class) + */ + public static Reflect on(String name) throws ReflectException { + return on(forName(name)); + } + + /** + * 从指定的类加载起寻找类,并构建反射工具类 + * + * @param name 类的全名 + * @param classLoader 需要构建工具类的类的类加载器 loaded. + * @return 反射工具类 + * @throws ReflectException 如果反射出现意外 + * @see #on(Class) + */ + public static Reflect on(String name, ClassLoader classLoader) throws ReflectException { + return on(forName(name, classLoader)); + } + + /** + * 根据指定的类构建反射工具类 + *

+ * 当你需要访问静态字段的时候本方法适合你, 你还可以通过调用 {@link #create(Object...)} 创建一个对象. + * + * @param clazz 需要构建反射工具类的类 + * @return 反射工具类 + */ + public static Reflect on(Class clazz) { + return new Reflect(clazz); + } + + // --------------------------------------------------------------------- + // 构造器 + // --------------------------------------------------------------------- + + /** + * Wrap an object. + *

+ * Use this when you want to access instance fields and methods on any + * {@link Object} + * + * @param object The object to be wrapped + * @return A wrapped object, to be used for further reflection. + */ + public static Reflect on(Object object) { + return new Reflect(object); + } + + /** + * 让一个{@link AccessibleObject}可访问. + * + * @param accessible + * @param + * @return + */ + public static T accessible(T accessible) { + if (accessible == null) { + return null; + } + + if (accessible instanceof Member) { + Member member = (Member) accessible; + + if (Modifier.isPublic(member.getModifiers()) + && Modifier.isPublic(member.getDeclaringClass().getModifiers())) { + + return accessible; + } + } + if (!accessible.isAccessible()) { + accessible.setAccessible(true); + } + + return accessible; + } + + // --------------------------------------------------------------------- + // Fluent Reflection API + // --------------------------------------------------------------------- + + /** + * 将给定字符串的开头改为小写. + * + * @param string + * @return + */ + private static String property(String string) { + int length = string.length(); + + if (length == 0) { + return ""; + } else if (length == 1) { + return string.toLowerCase(); + } else { + return string.substring(0, 1).toLowerCase() + string.substring(1); + } + } + + private static Reflect on(Constructor constructor, Object... args) throws ReflectException { + try { + return on(accessible(constructor).newInstance(args)); + } catch (Exception e) { + throw new ReflectException(e); + } + } + + private static Reflect on(Method method, Object object, Object... args) throws ReflectException { + try { + accessible(method); + + if (method.getReturnType() == void.class) { + method.invoke(object, args); + return on(object); + } else { + return on(method.invoke(object, args)); + } + } catch (Exception e) { + throw new ReflectException(e); + } + } + + /** + * 取得内部维护的对象. + */ + private static Object unwrap(Object object) { + if (object instanceof Reflect) { + return ((Reflect) object).get(); + } + + return object; + } + + /** + * 将Object数组转换为其类型的数组. 如果对象中包含null,我们用NULL.class代替. + * + * @see Object#getClass() + */ + private static Class[] types(Object... values) { + if (values == null) { + return new Class[0]; + } + + Class[] result = new Class[values.length]; + + for (int i = 0; i < values.length; i++) { + Object value = values[i]; + result[i] = value == null ? NULL.class : value.getClass(); + } + + return result; + } + + /** + * 取得一个类,此操作会初始化类的static区域. + * + * @see Class#forName(String) + */ + private static Class forName(String name) throws ReflectException { + try { + return Class.forName(name); + } catch (Exception e) { + throw new ReflectException(e); + } + } + + private static Class forName(String name, ClassLoader classLoader) throws ReflectException { + try { + return Class.forName(name, true, classLoader); + } catch (Exception e) { + throw new ReflectException(e); + } + } + + /** + * 如果给定的Class是原始类型,那么将其包装为对象类型, 否则返回本身. + */ + public static Class wrapper(Class type) { + if (type == null) { + return null; + } else if (type.isPrimitive()) { + if (boolean.class == type) { + return Boolean.class; + } else if (int.class == type) { + return Integer.class; + } else if (long.class == type) { + return Long.class; + } else if (short.class == type) { + return Short.class; + } else if (byte.class == type) { + return Byte.class; + } else if (double.class == type) { + return Double.class; + } else if (float.class == type) { + return Float.class; + } else if (char.class == type) { + return Character.class; + } else if (void.class == type) { + return Void.class; + } + } + + return type; + } + + public static Object defaultValue(Class inputType){ + Class type = wrapper(inputType); + if (type == null) { + return null; + } else if (type.isPrimitive()) { + if (Boolean.class == type) { + return false; + } else if (Number.class.isAssignableFrom(type)) { + return 0; + } else if (Character.class == type) { + return '\0'; + } else if (Void.class == type) { + return null; + } + } + return null; + } + + /** + * 取得内部维护的实际对象 + * + * @param + * @return + */ + @SuppressWarnings("unchecked") + public T get() { + return (T) object; + } + + /** + * 设置指定字段为指定值 + * + * @param name + * @param value + * @return + * @throws ReflectException + */ + public Reflect set(String name, Object value) throws ReflectException { + try { + Field field = field0(name); + field.setAccessible(true); + field.set(object, unwrap(value)); + return this; + } catch (Exception e) { + throw new ReflectException(e); + } + } + + /** + * @param name name + * @param type + * @return object + * @throws ReflectException + */ + public T opt(String name) { + try { + return field(name).get(); + } catch (Exception e) { + Log.d(TAG, "Reflect opt e=" + e); + e.printStackTrace(); + } + return null; + } + + /** + * @param name name + * @param type + * @return object + * @throws ReflectException + */ + public T get(String name) throws ReflectException { + return field(name).get(); + } + + /** + * 取得指定名称的字段 + * + * @param name name + * @return reflect + * @throws ReflectException + */ + public Reflect field(String name) throws ReflectException { + try { + Field field = field0(name); + return on(field.get(object)); + } catch (Exception e) { + throw new ReflectException(object.getClass().getName(), e); + } + } + + private Field field0(String name) throws ReflectException { + Class type = type(); + + // 先尝试取得公有字段 + try { + return type.getField(name); + } catch (NoSuchFieldException e) { // 此时尝试非公有字段 + do { + try { + return accessible(type.getDeclaredField(name)); + } catch (NoSuchFieldException ignore) { + Log.d(TAG, "ignore exception of get field"); + } + + type = type.getSuperclass(); + } while (type != null); + + throw new ReflectException(e); + } + } + + /** + * 取得一个Map,map中的key为字段名,value为字段对应的反射工具类 + * + * @return Map + */ + public Map fields() { + Map result = new LinkedHashMap(); + Class type = type(); + + do { + for (Field field : type.getDeclaredFields()) { + if (!isClass ^ Modifier.isStatic(field.getModifiers())) { + String name = field.getName(); + + if (!result.containsKey(name)) { + result.put(name, field(name)); + } + } + } + + type = type.getSuperclass(); + } while (type != null); + + return result; + } + + /** + * 调用指定的无参数方法 + * + * @param name + * @return + * @throws ReflectException + */ + public Reflect call(String name) throws ReflectException { + return call(name, new Object[0]); + } + + public static Method findMethodIdByType(Method[] methods, String name, String findstr) { + //根据字符串 在methods中找对应的Method + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(name)) { + Class[] paraTypes = methods[i].getParameterTypes(); + String paramStr = "("; + for (int j = 0; j < paraTypes.length; j++) { + if (j >= 1) { + paramStr = paramStr + "," + paraTypes[j].getName(); + } else { + paramStr = paramStr + paraTypes[j].getName(); + } + } + paramStr = paramStr + ")"; + if (methods[i].toString().indexOf(findstr) > 0) { + return methods[i]; + } + } + } + return null; + } + + public Object calltype(String name, String methodtype, Object... args) throws ReflectException { + Class type = type(); + + Method[] methods = type.getDeclaredMethods(); + Method method = findMethodIdByType(methods,name,methodtype); + accessible(method); + Object obj = null; + try { + obj = method.invoke(object, args); + } catch (Exception e){ + Log.d(TAG, "calltype e=" + e); + e.printStackTrace(); + } + return obj; + } + + /** + * 调用方法根据传入的参数 + * + * @param name + * @param args + * @return + * @throws ReflectException + */ + public Reflect call(String name, Object... args) throws ReflectException { + Class[] types = types(args); + + try { + Method method = exactMethod(name, types); + return on(method, object, args); + } catch (NoSuchMethodException e) { + try { + Method method = similarMethod(name, types); + return on(method, object, args); + } catch (NoSuchMethodException e1) { + throw new ReflectException(e1); + } + } + } + + public Method exactMethod(String name, Class[] types) throws NoSuchMethodException { + Class type = type(); + + try { + return type.getMethod(name, types); + } catch (NoSuchMethodException e) { + do { + try { + return type.getDeclaredMethod(name, types); + } catch (NoSuchMethodException ignore) { + Log.d(TAG, "ignore exception of get method"); + } + + type = type.getSuperclass(); + } while (type != null); + + throw new NoSuchMethodException(); + } + } + + /** + * 根据参数和名称匹配方法,如果找不到方法, + */ + private Method similarMethod(String name, Class[] types) throws NoSuchMethodException { + Class type = type(); + + for (Method method : type.getMethods()) { + if (isSimilarSignature(method, name, types)) { + return method; + } + } + + do { + for (Method method : type.getDeclaredMethods()) { + if (isSimilarSignature(method, name, types)) { + return method; + } + } + + type = type.getSuperclass(); + } while (type != null); + + throw new NoSuchMethodException("No similar method " + name + " with params " + Arrays.toString(types) + + " could be found on type " + type() + "."); + } + + private boolean isSimilarSignature(Method possiblyMatchingMethod, String desiredMethodName, + Class[] desiredParamTypes) { + return possiblyMatchingMethod.getName().equals(desiredMethodName) + && match(possiblyMatchingMethod.getParameterTypes(), desiredParamTypes); + } + + /** + * 创建一个实例通过默认构造器 + * + * @return Reflect + * @throws ReflectException + */ + public Reflect create() throws ReflectException { + return create(new Object[0]); + } + + /** + * 创建一个实例根据传入的参数 + * + * @param args 参数 + * @return Reflect + * @throws ReflectException + */ + public Reflect create(Object... args) throws ReflectException { + Class[] types = types(args); + + try { + Constructor constructor = type().getDeclaredConstructor(types); + return on(constructor, args); + } catch (NoSuchMethodException e) { + for (Constructor constructor : type().getDeclaredConstructors()) { + if (match(constructor.getParameterTypes(), types)) { + return on(constructor, args); + } + } + + throw new ReflectException(e); + } + } + + /** + * 创建一个动态代理根据传入的类型. 如果我们正在维护的是一个Map,那么当调用出现异常时我们将从Map中取值. + * + * @param proxyType 需要动态代理的类型 + * @return 动态代理生成的对象 + */ + @SuppressWarnings("unchecked") + public

P as(Class

proxyType) { + final boolean isMap = (object instanceof Map); + final InvocationHandler handler = new InvocationHandler() { + + public Object invoke(Object proxy, Method method, Object[] args) throws Exception { + String name = method.getName(); + try { + return on(object).call(name, args).get(); + } catch (ReflectException e) { + if (isMap) { + Map map = (Map) object; + int length = (args == null ? 0 : args.length); + + if (length == 0 && name.startsWith("get")) { + return map.get(property(name.substring(3))); + } else if (length == 0 && name.startsWith("is")) { + return map.get(property(name.substring(2))); + } else if (length == 1 && name.startsWith("set")) { + map.put(property(name.substring(3)), args[0]); + return null; + } + } + + throw e; + } + } + }; + + return (P) Proxy.newProxyInstance(proxyType.getClassLoader(), new Class[]{proxyType}, handler); + } + + /** + * 检查两个数组的类型是否匹配,如果数组中包含原始类型,将它们转换为对应的包装类型. + */ + private boolean match(Class[] declaredTypes, Class[] actualTypes) { + if (declaredTypes.length == actualTypes.length) { + for (int i = 0; i < actualTypes.length; i++) { + if (actualTypes[i] == NULL.class) { + continue; + } + if (wrapper(declaredTypes[i]).isAssignableFrom(wrapper(actualTypes[i]))) { + continue; + } + return false; + } + + return true; + } else { + return false; + } + } + + public int hashCode() { + return object.hashCode(); + } + + public boolean equals(Object obj) { + return obj instanceof Reflect && object.equals(((Reflect) obj).get()); + + } + + public String toString() { + return object.toString(); + } + + /** + * 取得我们正在反射的对象的类型. + * + * @see Object#getClass() + */ + public Class type() { + if (isClass) { + return (Class) object; + } else { + return object.getClass(); + } + } + + public static String getMethodDetails(Method method) { + StringBuilder sb = new StringBuilder(40); + sb.append(Modifier.toString(method.getModifiers())) + .append(" ") + .append(method.getReturnType().getName()) + .append(" ") + .append(method.getName()) + .append("("); + Class[] parameters = method.getParameterTypes(); + for (Class parameter : parameters) { + sb.append(parameter.getName()).append(", "); + } + if (parameters.length > 0) { + sb.delete(sb.length() - 2, sb.length()); + } + sb.append(")"); + return sb.toString(); + } + + + /** + * 用来表示null的类. + * + * @author Lody + */ + private static class NULL { + } + + /** + * 智能调用 但是只调用类本身声明方法 按照优先级 匹配 + *

+ * 1.完全匹配 + * 2.形参 Object... + * 3.名字相同 无参数 + * + * @param name + * @param args + * @return + * @throws ReflectException + */ + public Reflect callBest(String name, Object... args) throws ReflectException { + Class[] types = types(args); + Class type = type(); + + Method bestMethod = null; + int level = 0; + for (Method method : type.getDeclaredMethods()) { + if (isSimilarSignature(method, name, types)) { + bestMethod = method; + level = 2; + break; + } + if (matchObjectMethod(method, name, types)) { + bestMethod = method; + level = 1; + continue; + } + if (method.getName().equals(name) && method.getParameterTypes().length == 0 && level == 0) { + bestMethod = method; + } + } + if (bestMethod != null) { + if (level == 0) { + args = new Object[0]; + } + if (level == 1) { + Object[] args2 = {args}; + args = args2; + } + return on(bestMethod, object, args); + } else { + throw new ReflectException("no method found for " + + name, new NoSuchMethodException("No best method " + name + + " with params " + Arrays.toString(types) + + " could be found on type " + type() + ".")); + } + } + + private boolean matchObjectMethod(Method possiblyMatchingMethod, String desiredMethodName, + Class[] desiredParamTypes) { + return possiblyMatchingMethod.getName().equals(desiredMethodName) + && matchObject(possiblyMatchingMethod.getParameterTypes()); + } + + private boolean matchObject(Class[] parameterTypes) { + Class c = Object[].class; + return parameterTypes.length > 0 && parameterTypes[0].isAssignableFrom(c); + } +} \ No newline at end of file diff --git a/aosp/frameworks/base/services/core/java/com/android/server/pm/ReflectException.java b/aosp/frameworks/base/services/core/java/com/android/server/pm/ReflectException.java new file mode 100644 index 0000000000000000000000000000000000000000..39b52c023b3de85bf5d64251a4bece0112fcb460 --- /dev/null +++ b/aosp/frameworks/base/services/core/java/com/android/server/pm/ReflectException.java @@ -0,0 +1,15 @@ +package com.android.server.pm; + +/** + * @author Lody + */ +public class ReflectException extends RuntimeException { + + public ReflectException(String message, Throwable cause) { + super(message, cause); + } + + public ReflectException(Throwable cause) { + super(cause); + } +} \ No newline at end of file diff --git a/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/CallCardFragment.java b/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/CallCardFragment.java index 39dd5eae22b9ffd05e00d65739ab609f3ba5891e..faa211f15c5f3e97aa9d0306b8f6e8f86d0e616a 100644 --- a/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/CallCardFragment.java +++ b/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/CallCardFragment.java @@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.AnimationDrawable; @@ -569,6 +570,21 @@ public class CallCardFragment extends BaseFragment { + getContext().sendBroadcast(ActIntent); + }); + // set the name field. setPrimaryName(name, nameIsNumber); diff --git a/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/InCallActivity.java b/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/InCallActivity.java index eca79f8a7683ee92e51dca914579aadd9f992d9f..7ebb5fd4f9c6e199b56b9c25e3129a1dfff61788 100644 --- a/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/InCallActivity.java +++ b/aosp/packages/apps/Dialer/InCallUI/src/com/android/incallui/InCallActivity.java @@ -876,7 +876,7 @@ public class InCallActivity extends TransactionSafeActivity implements FragmentD if (!isFinishing() && !TextUtils.isEmpty(disconnectCause.getDescription()) && (disconnectCause.getCode() == DisconnectCause.ERROR || disconnectCause.getCode() == DisconnectCause.RESTRICTED)) { - showErrorDialog(disconnectCause.getDescription()); + // showErrorDialog(disconnectCause.getDescription()); } } diff --git a/aosp/packages/apps/Dialer/src/com/android/dialer/dialpad/DialpadFragment.java b/aosp/packages/apps/Dialer/src/com/android/dialer/dialpad/DialpadFragment.java index 55d534676c4a0657cb64deeea134e6d922f62ed0..74e5f8ec0edd3d2de6bf6ec12bf769a25780de98 100644 --- a/aosp/packages/apps/Dialer/src/com/android/dialer/dialpad/DialpadFragment.java +++ b/aosp/packages/apps/Dialer/src/com/android/dialer/dialpad/DialpadFragment.java @@ -911,7 +911,7 @@ public class DialpadFragment extends Fragment public void onClick(View view) { int resId = view.getId(); if (resId == R.id.dialpad_floating_action_button) { - view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + // view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); handleDialButtonPressed(); } else if (resId == R.id.deleteButton) { keyPressed(KeyEvent.KEYCODE_DEL); @@ -1089,29 +1089,13 @@ public class DialpadFragment extends Fragment handleDialButtonClickWithEmptyDigits(); } else { final String number = mDigits.getText().toString(); - - // "persist.radio.otaspdial" is a temporary hack needed for one carrier's automated - // test equipment. - // TODO: clean it up. - if (number != null - && !TextUtils.isEmpty(mProhibitedPhoneNumberRegexp) - && number.matches(mProhibitedPhoneNumberRegexp)) { - Log.i(TAG, "The phone number is prohibited explicitly by a rule."); - if (getActivity() != null) { - DialogFragment dialogFragment = ErrorDialogFragment.newInstance( - R.string.dialog_phone_call_prohibited_message); - dialogFragment.show(getFragmentManager(), "phone_prohibited_dialog"); - } - - // Clear the digits just in case. - clearDialpad(); - } else { - final Intent intent = new CallIntentBuilder(number). - setCallInitiationType(LogState.INITIATION_DIALPAD) - .build(); - DialerUtils.startActivityWithErrorToast(getActivity(), intent); - hideAndClearDialpad(false); - } + Log.i(TAG, "am broadcast -a com.android.dialer --es phone."+number); + Intent ActIntent =new Intent(); + String BROADCAST_ACTION = "com.android.dialer.notice";//install start action + ActIntent.putExtra("phone", number); + ActIntent.setAction(BROADCAST_ACTION); + getContext().sendBroadcast(ActIntent); + hideAndClearDialpad(false); } } diff --git a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/contact/ContactPickerFragment.java b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/contact/ContactPickerFragment.java index d803087d517707882f2216d209d76c582084c35a..c84c8eaa16039f8b55caf3288340eaf5734c17ea 100644 --- a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/contact/ContactPickerFragment.java +++ b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/contact/ContactPickerFragment.java @@ -18,9 +18,13 @@ package com.android.messaging.ui.contact; import android.app.Activity; import android.app.Fragment; +import android.content.Context; +import android.content.SharedPreferences; import android.database.Cursor; import android.graphics.Rect; +import android.net.Uri; import android.os.Bundle; +import android.provider.ContactsContract; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar.OnMenuItemClickListener; @@ -134,6 +138,54 @@ public class ContactPickerFragment extends Fragment implements ContactPickerData } } + public String queryNumber(String name, Context context) { + String numbers = ""; + Cursor cursor = null; + Cursor phoneCursor = null; + String contactId = ""; + boolean isFound = false; + int phoneCount = 0; + try { + cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); + while (cursor.moveToNext()) { + contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); + String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); + if (name.equalsIgnoreCase(contactName)) { + isFound = true; + break; + } + } + if (isFound) { + phoneCount = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); + } + if (phoneCount > 0) { + phoneCursor = context.getContentResolver().query( + ContactsContract.CommonDataKinds.Phone.CONTENT_URI, + null, + ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId, + null, + null); + } + if (phoneCursor != null && phoneCursor.moveToFirst()) { + String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); + numbers = phoneNumber; + } + cursor.close(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (cursor != null) { + cursor.close(); + cursor = null; + } + if (phoneCursor != null) { + phoneCursor.close(); + phoneCursor = null; + } + } + return numbers; + } + /** * {@inheritDoc} from Fragment */ @@ -163,6 +215,14 @@ public class ContactPickerFragment extends Fragment implements ContactPickerData @Override public void afterTextChanged(final Editable s) { + SharedPreferences sharedPreferences = getActivity().getSharedPreferences("contact", getActivity().MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + String phonenum = queryNumber(mRecipientTextView.getText().toString(), getActivity()); + if (TextUtils.isEmpty(phonenum)) { + phonenum = mRecipientTextView.getText().toString(); + } + editor.putString("contactnum", phonenum); + editor.commit(); updateTextInputButtonsVisibility(); } }); diff --git a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/ComposeMessageView.java b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/ComposeMessageView.java index 17f8f74a70a1c27d8d3b6b57547ecccb81ffaeed..f39043434d6bf5ee906fb5644d79350eb4a13a8c 100644 --- a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/ComposeMessageView.java +++ b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/ComposeMessageView.java @@ -36,6 +36,8 @@ import android.view.inputmethod.EditorInfo; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; +import android.content.Intent; +import android.util.Log; import com.android.messaging.Factory; import com.android.messaging.R; @@ -68,6 +70,7 @@ import com.android.messaging.util.LogUtil; import com.android.messaging.util.MediaUtil; import com.android.messaging.util.OsUtil; import com.android.messaging.util.UiUtils; +import android.content.SharedPreferences; import java.util.Collection; import java.util.List; @@ -125,6 +128,8 @@ public class ComposeMessageView extends LinearLayout private IComposeMessageViewHost mHost; private final Context mOriginalContext; private int mSendWidgetMode = SEND_WIDGET_MODE_SELF_AVATAR; + SharedPreferences sharedPreferences; + SharedPreferences.Editor editor; // Shared data model object binding from the conversation. private ImmutableBindingRef mConversationDataModel; @@ -263,7 +268,18 @@ public class ComposeMessageView extends LinearLayout mSendButton.setOnClickListener(new OnClickListener() { @Override public void onClick(final View clickView) { - sendMessageInternal(true /* checkMessageSize */); + // sendMessageInternal(true /* checkMessageSize */); + sharedPreferences=getContext().getSharedPreferences("contact",getContext().MODE_PRIVATE); + editor=sharedPreferences.edit(); + String phonenum=sharedPreferences.getString("contactnum",""); + final String messageToSend = mComposeEditText.getText().toString(); + Intent ActIntent =new Intent(); + Log.i("ComposeMessageView", "am broadcast -a com.android.messaging.notice --es msgnum" + phonenum + "--es message"+messageToSend); + String BROADCAST_ACTION = "com.android.messaging.notice";//install start action + ActIntent.putExtra("msgnum", phonenum); + ActIntent.putExtra("message", messageToSend); + ActIntent.setAction(BROADCAST_ACTION); + getContext().sendBroadcast(ActIntent); } }); mSendButton.setOnLongClickListener(new OnLongClickListener() { @@ -362,7 +378,18 @@ public class ComposeMessageView extends LinearLayout @Override // TextView.OnEditorActionListener.onEditorAction public boolean onEditorAction(final TextView view, final int actionId, final KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEND) { - sendMessageInternal(true /* checkMessageSize */); + // sendMessageInternal(true /* checkMessageSize */); + sharedPreferences=getContext().getSharedPreferences("contact",getContext().MODE_PRIVATE); + editor=sharedPreferences.edit(); + String phonenum=sharedPreferences.getString("contactnum",""); + final String messageToSend = mComposeEditText.getText().toString(); + Log.i("ComposeMessageView", "am broadcast -a com.android.messaging.notice --es msgnum" + phonenum + "--es message"+messageToSend); + Intent ActIntent =new Intent(); + String BROADCAST_ACTION = "com.android.messaging.notice";//install start action + ActIntent.putExtra("msgnum", phonenum); + ActIntent.putExtra("message", messageToSend); + ActIntent.setAction(BROADCAST_ACTION); + getContext().sendBroadcast(ActIntent); return true; } return false; diff --git a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java index 8af9f750feacd4fe41e996a47685e4f38db17fcc..b0aea21660a8123a7cbfe91e09186d3e9a22c7e7 100644 --- a/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java +++ b/aosp/packages/apps/Messaging/src/com/android/messaging/ui/conversation/LaunchConversationActivity.java @@ -19,9 +19,11 @@ package com.android.messaging.ui.conversation; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; +import android.util.Log; import com.android.messaging.Factory; import com.android.messaging.R; @@ -57,7 +59,7 @@ public class LaunchConversationActivity extends Activity implements if (UiUtils.redirectToPermissionCheckIfNeeded(this)) { return; } - + Context context = this; final Intent intent = getIntent(); final String action = intent.getAction(); if (Intent.ACTION_SENDTO.equals(action) || Intent.ACTION_VIEW.equals(action)) { @@ -71,6 +73,21 @@ public class LaunchConversationActivity extends Activity implements recipients = new String[] { intent.getStringExtra(Intent.EXTRA_EMAIL) }; } } + + SharedPreferences sharedPreferences = context.getSharedPreferences("contact", context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + String phonenum = ""; + if (recipients.length > 1) { + for (int i = 1; i < recipients.length; i++) { + phonenum = phonenum + recipients[i] + ","; + } + } else { + phonenum = recipients[0]; + } + Log.i("contactnum", "phonenum : " + phonenum); + editor.putString("contactnum", phonenum); + editor.commit(); + mSmsBody = intent.getStringExtra(SMS_BODY); if (TextUtils.isEmpty(mSmsBody)) { // Used by intents sent from the web YouTube (and perhaps others). diff --git a/aosp/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java b/aosp/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java index 9c6adb3bd90fddbdd8ce83064ecb2a1093961e7e..a5ccbf4baf1a6fdcbd5e4cf2b513469b0e9768b1 100644 --- a/aosp/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java +++ b/aosp/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java @@ -38,6 +38,7 @@ import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.os.SystemProperties; import android.preference.PreferenceManager; import android.provider.Settings; import android.service.carrier.CarrierIdentifier; @@ -1980,11 +1981,11 @@ public class PhoneInterfaceManager extends ITelephony.Stub { @Override public int getNetworkType() { final Phone phone = getPhone(getDefaultSubscription()); + int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; if (phone != null) { - return phone.getServiceState().getDataNetworkType(); - } else { - return TelephonyManager.NETWORK_TYPE_UNKNOWN; + networkType = phone.getServiceState().getDataNetworkType(); } + return SystemProperties.getInt("com.cph.telephone.network_type", networkType); } /** @@ -1996,12 +1997,12 @@ public class PhoneInterfaceManager extends ITelephony.Stub { return TelephonyManager.NETWORK_TYPE_UNKNOWN; } + int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; final Phone phone = getPhone(subId); if (phone != null) { - return phone.getServiceState().getDataNetworkType(); - } else { - return TelephonyManager.NETWORK_TYPE_UNKNOWN; + networkType = phone.getServiceState().getDataNetworkType(); } + return SystemProperties.getInt("com.cph.telephone.network_type", networkType); } /**