diff options
author | Dianne Hackborn <hackbod@google.com> | 2015-04-04 14:52:14 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2015-04-04 17:36:05 -0700 |
commit | d59a5d59df920d743723521a2afed9de1da3373b (patch) | |
tree | 2fa60c308b330a8203d00f1e99811e54c6f486a9 /services | |
parent | cef55cde1cf1b9b15583d6b4c439dfea7bac7c26 (diff) | |
download | frameworks_base-d59a5d59df920d743723521a2afed9de1da3373b.zip frameworks_base-d59a5d59df920d743723521a2afed9de1da3373b.tar.gz frameworks_base-d59a5d59df920d743723521a2afed9de1da3373b.tar.bz2 |
Various fixes and improvements...
Issue #19912529: VI: VoiceInteractor callback ClassCastException
Fix to use correct argument.
Issue #19912636: VI: Documentation for VoiceInteractionSession.onBackPressed
Added documentation.
Issue #19912703: VI: VoiceInteractionSession NPE on Abort Request
Maybe fix this -- don't crash if there is no active session.
Issue #19953731: VI: Add value index to...
...android.app.VoiceInteractor.PickOptionRequest.Option
There is now an optional index integer that can be associated with
every Option object.
Issue #19912635: VI: Behavior of startActivity when in voice...
...interaction is unexpected
We now forcibly finish the current voice interaction task whenever
another activity takes focus from it.
Issue #20066569: Add API to request heap dumps
New ActivityManager API to set the pss limit to generate heap
dumps.
Also added app ops for assist receiving structure and screenshot
data, so that we can track when it does these things.
Change-Id: I688d4ff8f0bd0b8b9e3390a32375b4bb7875c1a1
Diffstat (limited to 'services')
3 files changed, 126 insertions, 29 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index cdaa5a3..8895a15 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1124,7 +1124,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean mAutoStopProfiler = false; int mProfileType = 0; String mOpenGlTraceApp = null; - final ArrayMap<String, Long> mMemWatchProcesses = new ArrayMap<>(); + final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>(); String mMemWatchDumpProcName; String mMemWatchDumpFile; int mMemWatchDumpPid; @@ -1830,11 +1830,21 @@ public final class ActivityManagerService extends ActivityManagerNative final String procName; final int uid; final long memLimit; + final String reportPackage; synchronized (ActivityManagerService.this) { procName = mMemWatchDumpProcName; uid = mMemWatchDumpUid; - Long limit = mMemWatchProcesses.get(procName); - memLimit = limit != null ? limit : 0; + Pair<Long, String> val = mMemWatchProcesses.get(procName, uid); + if (val == null) { + val = mMemWatchProcesses.get(procName, 0); + } + if (val != null) { + memLimit = val.first; + reportPackage = val.second; + } else { + memLimit = 0; + reportPackage = null; + } } if (procName == null) { return; @@ -1867,6 +1877,9 @@ public final class ActivityManagerService extends ActivityManagerNative intent.setClassName("android", DumpHeapActivity.class.getName()); intent.putExtra(DumpHeapActivity.KEY_PROCESS, procName); intent.putExtra(DumpHeapActivity.KEY_SIZE, memLimit); + if (reportPackage != null) { + intent.putExtra(DumpHeapActivity.KEY_DIRECT_LAUNCH, reportPackage); + } int userId = UserHandle.getUserId(uid); notification.setLatestEventInfo(mContext, text, mContext.getText(R.string.dump_heap_notification_detail), @@ -2474,11 +2487,19 @@ public final class ActivityManagerService extends ActivityManagerNative final void setFocusedActivityLocked(ActivityRecord r, String reason) { if (r != null && mFocusedActivity != r) { if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r); + ActivityRecord last = mFocusedActivity; mFocusedActivity = r; if (r.task != null && r.task.voiceInteractor != null) { startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid); } else { finishRunningVoiceLocked(); + if (last != null && last.task.voiceSession != null) { + // We had been in a voice interaction session, but now focused has + // move to something different. Just finish the session, we can't + // return to it and retain the proper state and synchronization with + // the voice interaction service. + finishVoiceTask(last.task.voiceSession); + } } if (mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity")) { mWindowManager.setFocusedApp(r.appToken, true); @@ -12856,16 +12877,28 @@ public final class ActivityManagerService extends ActivityManagerNative + " mOrigWaitForDebugger=" + mOrigWaitForDebugger); } } - if (mMemWatchProcesses.size() > 0) { + if (mMemWatchProcesses.getMap().size() > 0) { pw.println(" Mem watch processes:"); - for (int i=0; i<mMemWatchProcesses.size(); i++) { - if (needSep) { - pw.println(); - needSep = false; + final ArrayMap<String, SparseArray<Pair<Long, String>>> procs + = mMemWatchProcesses.getMap(); + for (int i=0; i<procs.size(); i++) { + final String proc = procs.keyAt(i); + final SparseArray<Pair<Long, String>> uids = procs.valueAt(i); + for (int j=0; j<uids.size(); j++) { + if (needSep) { + pw.println(); + needSep = false; + } + StringBuilder sb = new StringBuilder(); + sb.append(" ").append(proc).append('/'); + UserHandle.formatUid(sb, uids.keyAt(j)); + Pair<Long, String> val = uids.valueAt(i); + sb.append(": "); DebugUtils.sizeValueToString(val.first, sb); + if (val.second != null) { + sb.append(", report to ").append(val.second); + } + pw.println(sb.toString()); } - pw.print(" "); pw.print(mMemWatchProcesses.keyAt(i)); - pw.print(": "); DebugUtils.printSizeValue(pw, mMemWatchProcesses.valueAt(i)); - pw.println(); } pw.print(" mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName); pw.print(" mMemWatchDumpFile="); pw.println(mMemWatchDumpFile); @@ -17390,7 +17423,18 @@ public final class ActivityManagerService extends ActivityManagerNative proc.lastCachedPss = pss; } - Long check = mMemWatchProcesses.get(proc.processName); + final SparseArray<Pair<Long, String>> watchUids + = mMemWatchProcesses.getMap().get(proc.processName); + Long check = null; + if (watchUids != null) { + Pair<Long, String> val = watchUids.get(proc.uid); + if (val == null) { + val = watchUids.get(0); + } + if (val != null) { + check = val.first; + } + } if (check != null) { if ((pss * 1024) >= check && proc.thread != null && mMemWatchDumpProcName == null) { boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); @@ -17426,7 +17470,8 @@ public final class ActivityManagerService extends ActivityManagerNative IApplicationThread thread = myProc.thread; if (thread != null) { try { - if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting dump heap from " + if (true || DEBUG_PSS) Slog.d(TAG_PSS, + "Requesting dump heap from " + myProc + " to " + heapdumpFile); thread.dumpHeap(true, heapdumpFile.toString(), fd); } catch (RemoteException e) { @@ -18661,15 +18706,38 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void setDumpHeapDebugLimit(String processName, long maxMemSize) { - enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP, - "setDumpHeapDebugLimit()"); + public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize, + String reportPackage) { + if (processName != null) { + enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP, + "setDumpHeapDebugLimit()"); + } else { + if (!Build.IS_DEBUGGABLE) { + throw new SecurityException("Not running a debuggable build"); + } + synchronized (mPidsSelfLocked) { + ProcessRecord proc = mPidsSelfLocked.get(Binder.getCallingPid()); + if (proc == null) { + throw new SecurityException("No process found for calling pid " + + Binder.getCallingPid()); + } + processName = proc.processName; + uid = proc.uid; + if (reportPackage != null && !proc.pkgList.containsKey(reportPackage)) { + throw new SecurityException("Package " + reportPackage + " is not running in " + + proc); + } + } + } synchronized (this) { if (maxMemSize > 0) { - mMemWatchProcesses.put(processName, maxMemSize); - mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG); + mMemWatchProcesses.put(processName, uid, new Pair(maxMemSize, reportPackage)); } else { - mMemWatchProcesses.remove(processName); + if (uid != 0) { + mMemWatchProcesses.remove(processName, uid); + } else { + mMemWatchProcesses.getMap().remove(processName); + } } } } @@ -18687,7 +18755,7 @@ public final class ActivityManagerService extends ActivityManagerNative + " does not match last path " + mMemWatchDumpFile); return; } - if (DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path); + if (true || DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path); mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG); } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index 1aa0d0b..bca757b 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -145,7 +145,10 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne } public boolean hideSessionLocked(int callingPid, int callingUid) { - return mActiveSession.hideLocked(); + if (mActiveSession != null) { + return mActiveSession.hideLocked(); + } + return false; } public boolean deliverNewSessionLocked(int callingPid, int callingUid, IBinder token, @@ -165,6 +168,10 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne Slog.w(TAG, "startVoiceActivity does not match active session"); return ActivityManager.START_CANCELED; } + if (!mActiveSession.mShown) { + Slog.w(TAG, "startVoiceActivity not allowed on hidden session"); + return ActivityManager.START_CANCELED; + } intent = new Intent(intent); intent.addCategory(Intent.CATEGORY_VOICE); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java index 73c7363..607df2d 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -18,6 +18,7 @@ package com.android.server.voiceinteraction; import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.AppOpsManager; import android.app.AssistContent; import android.app.IActivityManager; import android.content.ClipData; @@ -62,6 +63,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { final int mCallingUid; final IActivityManager mAm; final IWindowManager mIWindowManager; + final AppOpsManager mAppOps; final IBinder mPermissionOwner; boolean mShown; Bundle mShowArgs; @@ -148,6 +150,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { mAm = ActivityManagerNative.getDefault(); mIWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); + mAppOps = context.getSystemService(AppOpsManager.class); IBinder permOwner = null; try { permOwner = mAm.newUriPermissionOwner("voicesession:" @@ -159,7 +162,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE); mBindIntent.setComponent(mSessionComponentName); mBound = mContext.bindServiceAsUser(mBindIntent, this, - Context.BIND_AUTO_CREATE|Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser)); + Context.BIND_AUTO_CREATE|Context.BIND_WAIVE_PRIORITY + |Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser)); if (mBound) { try { mIWindowManager.addWindowToken(mToken, @@ -186,19 +190,31 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { mShowFlags = flags; mHaveAssistData = false; if ((flags&VoiceInteractionService.START_WITH_ASSIST) != 0) { - try { - mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL, - mAssistReceiver); - } catch (RemoteException e) { + if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid, + mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED) { + try { + mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL, + mAssistReceiver); + } catch (RemoteException e) { + } + } else { + mHaveAssistData = true; + mAssistData = null; } } else { mAssistData = null; } mHaveScreenshot = false; if ((flags&VoiceInteractionService.START_WITH_SCREENSHOT) != 0) { - try { - mIWindowManager.requestAssistScreenshot(mScreenshotReceiver); - } catch (RemoteException e) { + if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_SCREENSHOT, mCallingUid, + mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED) { + try { + mIWindowManager.requestAssistScreenshot(mScreenshotReceiver); + } catch (RemoteException e) { + } + } else { + mHaveScreenshot = true; + mScreenshot = null; } } else { mScreenshot = null; @@ -335,6 +351,12 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { mUser); } catch (RemoteException e) { } + if (mSession != null) { + try { + mAm.finishVoiceTask(mSession); + } catch (RemoteException e) { + } + } } if (mFullyBound) { mContext.unbindService(mFullConnection); |