目录

1.概述

2.系统frameworks禁止进入应用信息页的核心代码

3.系统frameworks禁止进入应用信息页的核心代码功能分析

3.1AppErrorDialog.java关于错误信息的分析

3.2 AppErrors.java的相关代码

3.3 ContextImpl.java关于启动Activity的相关代码调用

3.4 Activity.java中关于禁止启动应用信息的相关代码


1.概述

在定制化开发中,在app崩溃后,会弹出弹窗提醒崩溃了,然后弹窗可以通过点击应用信息按钮进入应用信息页这对于权限的管控不好处理,所以要求frameworks层禁止通过activity进入应用详情页

2.系统frameworks禁止进入应用信息页的核心代码

   frameworks/base/core/java/android/app/Activity.javaframeworks/base/core/java/android/app/ContextImpl.javaframeworks/base/services/core/java/com/android/server/am/AppErrorDialog.javaframeworks/base/services/core/java/com/android/server/am/AppErrors.java

3.系统frameworks禁止进入应用信息页的核心代码功能分析

3.1AppErrorDialog.java关于错误信息的分析

  final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListener {private final ActivityManagerService mService;private final AppErrorResult mResult;private final ProcessRecord mProc;private final boolean mIsRestartable;static int CANT_SHOW = -1;static int BACKGROUND_USER = -2;static int ALREADY_SHOWING = -3;// Event 'what' codesstatic final int FORCE_QUIT = 1;static final int FORCE_QUIT_AND_REPORT = 2;static final int RESTART = 3;static final int MUTE = 5;static final int TIMEOUT = 6;static final int CANCEL = 7;static final int APP_INFO = 8;// 5-minute timeout, then we automatically dismiss the crash dialogstatic final long DISMISS_TIMEOUT = 1000 * 60 * 5;public AppErrorDialog(Context context, ActivityManagerService service, Data data) {super(context);Resources res = context.getResources();mService = service;mProc = data.proc;mResult = data.result;mIsRestartable = (data.taskId != INVALID_TASK_ID || data.isRestartableForService)&& Settings.Global.getInt(context.getContentResolver(),Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG, 0) != 0;BidiFormatter bidi = BidiFormatter.getInstance();CharSequence name;if ((mProc.pkgList.size() == 1) &&(name = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {setTitle(res.getString(data.repeating ? com.android.internal.R.string.aerr_application_repeated: com.android.internal.R.string.aerr_application,bidi.unicodeWrap(name.toString()),bidi.unicodeWrap(mProc.info.processName)));} else {name = mProc.processName;setTitle(res.getString(data.repeating ? com.android.internal.R.string.aerr_process_repeated: com.android.internal.R.string.aerr_process,bidi.unicodeWrap(name.toString())));}setCancelable(true);setCancelMessage(mHandler.obtainMessage(CANCEL));WindowManager.LayoutParams attrs = getWindow().getAttributes();attrs.setTitle("Application Error: " + mProc.info.processName);attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR| WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;getWindow().setAttributes(attrs);if (mProc.isPersistent()) {getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);}// After the timeout, pretend the user clicked the quit buttonmHandler.sendMessageDelayed(mHandler.obtainMessage(TIMEOUT),DISMISS_TIMEOUT);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);final FrameLayout frame = findViewById(android.R.id.custom);final Context context = getContext();LayoutInflater.from(context).inflate(com.android.internal.R.layout.app_error_dialog, frame, true);final boolean hasReceiver = mProc.errorReportReceiver != null;final TextView restart = findViewById(com.android.internal.R.id.aerr_restart);restart.setOnClickListener(this);restart.setVisibility(mIsRestartable ? View.VISIBLE : View.GONE);final TextView report = findViewById(com.android.internal.R.id.aerr_report);report.setOnClickListener(this);report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);final TextView close = findViewById(com.android.internal.R.id.aerr_close);close.setOnClickListener(this);final TextView appInfo = findViewById(com.android.internal.R.id.aerr_app_info);appInfo.setOnClickListener(this);boolean showMute = !Build.IS_USER && Settings.Global.getInt(context.getContentResolver(),Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0&& Settings.Global.getInt(context.getContentResolver(),Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG, 0) != 0;final TextView mute = findViewById(com.android.internal.R.id.aerr_mute);mute.setOnClickListener(this);mute.setVisibility(showMute ? View.VISIBLE : View.GONE);findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);}@Overridepublic void onStart() {super.onStart();getContext().registerReceiver(mReceiver,new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));}@Overrideprotected void onStop() {super.onStop();getContext().unregisterReceiver(mReceiver);}private final Handler mHandler = new Handler() {public void handleMessage(Message msg) {setResult(msg.what);dismiss();}};@Overridepublic void dismiss() {if (!mResult.mHasResult) {// We are dismissing and the result has not been set...go ahead and set.setResult(FORCE_QUIT);}super.dismiss();}private void setResult(int result) {synchronized (mService) {if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {mProc.crashDialog = null;}}mResult.set(result);// Make sure we don't have time timeout still hanging around.mHandler.removeMessages(TIMEOUT);}@Overridepublic void onClick(View v) {switch (v.getId()) {case com.android.internal.R.id.aerr_restart:mHandler.obtainMessage(RESTART).sendToTarget();break;case com.android.internal.R.id.aerr_report:mHandler.obtainMessage(FORCE_QUIT_AND_REPORT).sendToTarget();break;case com.android.internal.R.id.aerr_close:mHandler.obtainMessage(FORCE_QUIT).sendToTarget();break;case com.android.internal.R.id.aerr_app_info:mHandler.obtainMessage(APP_INFO).sendToTarget();break;case com.android.internal.R.id.aerr_mute:mHandler.obtainMessage(MUTE).sendToTarget();break;default:break;}}private void setResult(int result) {synchronized (mService) {if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {mProc.crashDialog = null;}}mResult.set(result);// Make sure we don't have time timeout still hanging around.mHandler.removeMessages(TIMEOUT);}final class AppErrorResult {public void set(int res) {synchronized (this) {mHasResult = true;mResult = res;notifyAll();}}public int get() {synchronized (this) {while (!mHasResult) {try {wait();} catch (InterruptedException e) {}}}return mResult;}boolean mHasResult = false;int mResult;
}

在AppErrorDialog中,从源码中就是在app崩溃的时候,弹窗弹出停止运行和查看应用详情这两个选项,所以可以从查看应用详情的相关源码注释掉相关源码

3.2 AppErrors.java的相关代码

void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {final int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();try {crashApplicationInner(r, crashInfo, callingPid, callingUid);} finally {Binder.restoreCallingIdentity(origId);}}void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,int callingPid, int callingUid) {long timeMillis = System.currentTimeMillis();String shortMsg = crashInfo.exceptionClassName;String longMsg = crashInfo.exceptionMessage;String stackTrace = crashInfo.stackTrace;if (shortMsg != null && longMsg != null) {longMsg = shortMsg + ": " + longMsg;} else if (shortMsg != null) {longMsg = shortMsg;}if (r != null) {boolean isApexModule = false;try {for (String androidPackage : r.getPackageList()) {ModuleInfo moduleInfo = mContext.getPackageManager().getModuleInfo(androidPackage, /*flags=*/ 0);if (moduleInfo != null) {isApexModule = true;break;}}} catch (IllegalStateException | PackageManager.NameNotFoundException e) {// Call to PackageManager#getModuleInfo() can result in NameNotFoundException or// IllegalStateException. In case they are thrown, there isn't much we can do// other than proceed with app crash handling.}if (r.isPersistent() || isApexModule) {// If a persistent app or apex module is stuck in a crash loop, the device isn't// very usable, so we want to consider sending out a rescue party.RescueParty.noteAppCrash(mContext, r.uid);}mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode());}final int relaunchReason = r != null? r.getWindowProcessController().computeRelaunchReason() : RELAUNCH_REASON_NONE;AppErrorResult result = new AppErrorResult();int taskId;synchronized (mService) {/*** If crash is handled by instance of {@link android.app.IActivityController},* finish now and don't show the app error dialog.*/if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,timeMillis, callingPid, callingUid)) {return;}// Suppress crash dialog if the process is being relaunched due to a crash during a free// resize.if (relaunchReason == RELAUNCH_REASON_FREE_RESIZE) {return;}/*** If this process was running instrumentation, finish now - it will be handled in* {@link ActivityManagerService#handleAppDiedLocked}.*/if (r != null && r.getActiveInstrumentation() != null) {return;}// Log crash in battery stats.if (r != null) {mService.mBatteryStatsService.noteProcessCrash(r.processName, r.uid);}AppErrorDialog.Data data = new AppErrorDialog.Data();data.result = result;data.proc = r;// If we can't identify the process or it's already exceeded its crash quota,// quit right away without showing a crash dialog.if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {return;}final Message msg = Message.obtain();msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;taskId = data.taskId;msg.obj = data;mService.mUiHandler.sendMessage(msg);}int res = result.get();Intent appErrorIntent = null;MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {res = AppErrorDialog.FORCE_QUIT;}synchronized (mService) {if (res == AppErrorDialog.MUTE) {stopReportingCrashesLocked(r);}if (res == AppErrorDialog.RESTART) {mService.mProcessList.removeProcessLocked(r, false, true, "crash");if (taskId != INVALID_TASK_ID) {try {mService.startActivityFromRecents(taskId,ActivityOptions.makeBasic().toBundle());} catch (IllegalArgumentException e) {// Hmm...that didn't work. Task should either be in recents or associated// with a stack.Slog.e(TAG, "Could not restart taskId=" + taskId, e);}}}if (res == AppErrorDialog.FORCE_QUIT) {long orig = Binder.clearCallingIdentity();try {// Kill it with fire!mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());if (!r.isPersistent()) {mService.mProcessList.removeProcessLocked(r, false, false, "crash");mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);}} finally {Binder.restoreCallingIdentity(orig);}}if (res == AppErrorDialog.APP_INFO) {appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);}if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);}if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {// XXX Can't keep track of crash time for isolated processes,// since they don't have a persistent identity.mProcessCrashTimes.put(r.info.processName, r.uid,SystemClock.uptimeMillis());}}if (appErrorIntent != null) {try {mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));} catch (ActivityNotFoundException e) {Slog.w(TAG, "bug report receiver dissappeared", e);}}}

从这段代码可以看出调用的是Settings.ACTION_APPLICATION_DETAILS_SETTINGS的intent应用信息页调转
            if (res == AppErrorDialog.APP_INFO) {
                appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
                appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
最后通过mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));来调整到应用信息页

3.3 ContextImpl.java关于启动Activity的相关代码调用

  class ContextImpl extends Context {private final static String TAG = "ContextImpl";private final static boolean DEBUG = false;private static final String XATTR_INODE_CACHE = "user.inode_cache";private static final String XATTR_INODE_CODE_CACHE = "user.inode_code_cache";/*** Map from package name, to preference name, to cached preferences.*/@GuardedBy("ContextImpl.class")@UnsupportedAppUsageprivate static ArrayMap<String, ArrayMap<File, SharedPreferencesImpl>> sSharedPrefsCache;/*** Map from preference name to generated path.*/@GuardedBy("ContextImpl.class")@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)private ArrayMap<String, File> mSharedPrefsPaths;@UnsupportedAppUsagefinal @NonNull ActivityThread mMainThread;@UnsupportedAppUsagefinal @NonNull LoadedApk mPackageInfo;@UnsupportedAppUsageprivate @Nullable ClassLoader mClassLoader;private final @Nullable IBinder mActivityToken;private final @NonNull UserHandle mUser;@UnsupportedAppUsagestatic ContextImpl getImpl(Context context) {Context nextContext;while ((context instanceof ContextWrapper) &&(nextContext=((ContextWrapper)context).getBaseContext()) != null) {context = nextContext;}return (ContextImpl)context;}@Overridepublic AssetManager getAssets() {return getResources().getAssets();}@Overridepublic Resources getResources() {return mResources;}@Overridepublic PackageManager getPackageManager() {if (mPackageManager != null) {return mPackageManager;}IPackageManager pm = ActivityThread.getPackageManager();if (pm != null) {// Doesn't matter if we make more than one instance.return (mPackageManager = new ApplicationPackageManager(this, pm));}return null;}@Overridepublic ContentResolver getContentResolver() {return mContentResolver;}@Overridepublic Looper getMainLooper() {return mMainThread.getLooper();}@Overridepublic Executor getMainExecutor() {return mMainThread.getExecutor();}@Overridepublic Context getApplicationContext() {return (mPackageInfo != null) ?mPackageInfo.getApplication() : mMainThread.getApplication();}@Overridepublic void setTheme(int resId) {synchronized (mSync) {if (mThemeResource != resId) {mThemeResource = resId;initializeTheme();}}}@Overridepublic int getThemeResId() {synchronized (mSync) {return mThemeResource;}}@Overridepublic Resources.Theme getTheme() {synchronized (mSync) {if (mTheme != null) {return mTheme;}mThemeResource = Resources.selectDefaultTheme(mThemeResource,getOuterContext().getApplicationInfo().targetSdkVersion);initializeTheme();return mTheme;}}private void initializeTheme() {if (mTheme == null) {mTheme = mResources.newTheme();}mTheme.applyStyle(mThemeResource, true);}@Overridepublic ClassLoader getClassLoader() {return mClassLoader != null ? mClassLoader : (mPackageInfo != null ? mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader());}@Overridepublic String getPackageName() {if (mPackageInfo != null) {return mPackageInfo.getPackageName();}// No mPackageInfo means this is a Context for the system itself,// and this here is its name.return "android";}/** @hide */@Overridepublic String getBasePackageName() {return mBasePackageName != null ? mBasePackageName : getPackageName();}@Overridepublic void startActivity(Intent intent) {// add core startif(intent==null)return;String action = intent.getAction();if(DEBUG)Log.e("ContextImpl","startActivity--action:"+action);if(action!=null&&action.equals("android.settings.APPLICATION_DETAILS_SETTINGS"))return;//add core endwarnIfCallingFromSystemProcess();startActivity(intent, null);}/** @hide */@Overridepublic void startActivityAsUser(Intent intent, UserHandle user) {// add core startif(intent==null)return;String action = intent.getAction();if(DEBUG)Log.e("ContextImpl","startActivityAsUser--action:"+action);if(action!=null&&action.equals("android.settings.APPLICATION_DETAILS_SETTINGS"))return;//add core endstartActivityAsUser(intent, null, user);}}

在ContextImpl.java的startActivity(Intent intent)和startActivityAsUser(Intent intent, UserHandle user)中判断是否是关于应用信息的启动信息 然后禁止启动就行了

3.4 Activity.java中关于禁止启动应用信息的相关代码

/*** Same as {@link #startActivity(Intent, Bundle)} with no options* specified.** @param intent The intent to start.** @throws android.content.ActivityNotFoundException** @see #startActivity(Intent, Bundle)* @see #startActivityForResult*/@Overridepublic void startActivity(Intent intent) {// add core startif(intent==null)return;String action = intent.getAction();if(DEBUG_LIFECYCLE)Log.e("Activity","startActivity--action:"+action);if(action!=null&&action.equals("android.settings.APPLICATION_DETAILS_SETTINGS"))return;//add core endthis.startActivity(intent, null);}/*** @hide Implement to provide correct calling token.*/@Overridepublic void startActivityAsUser(Intent intent, UserHandle user) {// add core startif(intent==null)return;String action = intent.getAction();if(DEBUG_LIFECYCLE)Log.e("Activity","action:"+action);if(action!=null&&action.equals("android.settings.APPLICATION_DETAILS_SETTINGS"))return;//add core endstartActivityAsUser(intent, null, user);}

在Activity中的startActivity(Intent intent)和startActivityAsUser(Intent intent, UserHandle user)中判断是否是关于应用信息的启动信息 然后禁止启动就行了,这样就达到了禁用查看应用详情的功能

Android 10.0 系统framework禁止访问应用信息页相关推荐

  1. android 10.0系统 跳转 使用WPS打开文档

    android 10.0系统 跳转 使用WPS打开文档 1.AndroidManifest.xml配置 <provider android:name="android.support. ...

  2. Android 10.0 系统默认开启wifi

    1.概述 在10.0的系统产品中wifi是默认关闭的,由于的纯wifi的产品,所以需要要求默认打开wifi,开机后直接连wifi就可以了 所以需要找到相关的开关默认打开就可以了,然后开始连接wifi ...

  3. Android 10.0 Launcher3桌面禁止左右滑动

    1.1概述 在10.0的rom定制化开发中,由于Launcher3有一些功能需要定制,这样的需求也好多的,现在功能需求要求桌面固定在Launcher3的app列表页,不让左右移动,就是禁止左右移动的功 ...

  4. Android 10.0 系统禁用深色主题背景功能

    目录 1.概述 2.系统禁用深色主题背景功能相关核心代码

  5. 猿创征文|Android 10.0 系统去掉省电模式

    目录 1.概述 2.核心代码 3.核心代码功能分析 3.1BatterySaverTile.java 省电模式功能开关相关代码 1.概述 在系统中系统设置里面省电模式的选择中,有智能省电模式 省电模式 ...

  6. Android 10.0 系统去掉连续按两次电源键打开摄像头功能

    目录 1.概述 2.系统去掉连续按两次电源键打开摄像头功能的核心代码

  7. 华为内测基于Android 10.0的EMUI 10系统;2019年Q1真无线耳机市场份额,苹果占半壁江山……...

    关注并标星星CSDN云计算 极客头条:速递.最新.绝对有料.这里有企业新动.这里有业界要闻,打起十二分精神,紧跟fashion你可以的! 每周三次,打卡即read 更快.更全了解泛云圈精彩news g ...

  8. 华为EMUI 10系统内测截图曝光:基于Android 10.0

    日前有消息称,华为正在内测基于Android 10.0系统的EMUI 10系统,该系统不仅在内核方面得以升级,更会内置全套谷歌GMS套件. 从目前流出的截图来看,内测机型仅限今年上半年推出的旗舰产品华 ...

  9. android屏幕适配的五种方式_讲一讲Android 9.0系统的新特性,对刘海屏设备进行适配...

    黑客技术点击右侧关注,了解黑客的世界! Java开发进阶点击右侧关注,掌握进阶之路! Python开发点击右侧关注,探讨技术话题!作者丨郭霖来源丨郭霖(guolin_blog) 其实Android 9 ...

最新文章

  1. Changes at Different Environment?
  2. 《Linux内核设计与实现》读书笔记(十一)- 定时器和时间管理
  3. RabbitMQ 上手记录-part 1-基础概念
  4. centos 对已有卷扩容_centos7 逻辑卷扩容
  5. python3编程教学_Python3 网络编程
  6. vb语言程序设计_如果编程语言难度决定头发浓度,学这语言的可能要光头了
  7. 师--链表的结点插入
  8. python代码_python爬虫19 | 遇到需要的登录的网站怎么办?用这3招轻松搞定!
  9. cx_oracle写日志信息_浅谈微服务架构之构建日志收集系统
  10. 洛谷 1192:台阶问题(递推,DP)
  11. MySQL之环境变量配置
  12. linux允许8000端口,Linux中如何开启8080端口供外界访问 和开启允许对外访问的端口8000...
  13. 地址栏中的#是什么意思
  14. 科学家发现孤独感与大脑中的默认网络有关
  15. JavaScript动态加载效果
  16. 硬件测试工程师的待遇和前景
  17. ViewPager中呈现前一页和后一页的内容
  18. uboot启动之BL1阶段的分析1
  19. Docker——阿里云搭建Docker Swarm集群
  20. Chapter5 生长因子、受体和癌症

热门文章

  1. python安在d盘_python安装c盘还是d盘-女性时尚流行美容健康娱乐mv-ida网
  2. QMutex 的使用
  3. 神漏洞!一张高清照片,破解三星Galaxy S8虹膜识别
  4. 打印选课学生名单 (25 分)
  5. 盘古开源:跨国车企开年即削减产量,芯片危机2022年仍无望缓解?
  6. 未来监护人:FCC专员正在努力推迟网络中立投票
  7. GBDT + LR模型融合
  8. 安全狗重磅发布数据安全解决方案·数垒
  9. 微信7.0.15内测版本更新,黑暗模式将独立,还新增了这些功能!
  10. 高职计算机应用专业课程,高职计算机应用技术专业课程改革