summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2015-04-04 14:52:14 -0700
committerDianne Hackborn <hackbod@google.com>2015-04-04 17:36:05 -0700
commitd59a5d59df920d743723521a2afed9de1da3373b (patch)
tree2fa60c308b330a8203d00f1e99811e54c6f486a9 /services
parentcef55cde1cf1b9b15583d6b4c439dfea7bac7c26 (diff)
downloadframeworks_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')
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java108
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java9
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java38
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);