use of android.util.SparseArray in project android_frameworks_base by DirtyUnicorns.
the class MessageUtils method findMessageNames.
/**
* Finds the names of integer constants. Searches the specified {@code classes}, looking for
* accessible static integer fields whose names begin with one of the specified {@prefixes}.
*
* @param classes the classes to examine.
* @prefixes only consider fields names starting with one of these prefixes.
* @return a {@link SparseArray} mapping integer constants to their names.
*/
public static SparseArray<String> findMessageNames(Class[] classes, String[] prefixes) {
SparseArray<String> messageNames = new SparseArray<>();
for (Class c : classes) {
String className = c.getName();
if (DBG)
Log.d(TAG, "Examining class " + className);
Field[] fields;
try {
fields = c.getDeclaredFields();
} catch (SecurityException e) {
Log.e(TAG, "Can't list fields of class " + className);
continue;
}
for (Field field : fields) {
int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifiers) | !Modifier.isFinal(modifiers)) {
continue;
}
String name = field.getName();
for (String prefix : prefixes) {
// Does this look like a constant?
if (!name.startsWith(prefix)) {
continue;
}
try {
// TODO: can we have the caller try to access the field instead, so we don't
// expose constants it does not have access to?
field.setAccessible(true);
// Fetch the constant's value.
int value;
try {
value = field.getInt(null);
} catch (IllegalArgumentException | ExceptionInInitializerError e) {
// Either way, give up on this field.
break;
}
// Check for duplicate values.
String previousName = messageNames.get(value);
if (previousName != null && !previousName.equals(name)) {
throw new DuplicateConstantError(name, previousName, value);
}
messageNames.put(value, name);
if (DBG) {
Log.d(TAG, String.format("Found constant: %s.%s = %d", className, name, value));
}
} catch (SecurityException | IllegalAccessException e) {
// Not allowed to make the field accessible, or no access. Ignore.
continue;
}
}
}
}
return messageNames;
}
use of android.util.SparseArray in project android_frameworks_base by DirtyUnicorns.
the class PhoneWindow method saveHierarchyState.
/** {@inheritDoc} */
@Override
public Bundle saveHierarchyState() {
Bundle outState = new Bundle();
if (mContentParent == null) {
return outState;
}
SparseArray<Parcelable> states = new SparseArray<Parcelable>();
mContentParent.saveHierarchyState(states);
outState.putSparseParcelableArray(VIEWS_TAG, states);
// Save the focused view ID.
final View focusedView = mContentParent.findFocus();
if (focusedView != null && focusedView.getId() != View.NO_ID) {
outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
}
// save the panels
SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
savePanelState(panelStates);
if (panelStates.size() > 0) {
outState.putSparseParcelableArray(PANELS_TAG, panelStates);
}
if (mDecorContentParent != null) {
SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();
mDecorContentParent.saveToolbarHierarchyState(actionBarStates);
outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);
}
return outState;
}
use of android.util.SparseArray in project android_frameworks_base by DirtyUnicorns.
the class UserSwitcherController method refreshUsers.
/**
* Refreshes users from UserManager.
*
* The pictures are only loaded if they have not been loaded yet.
*
* @param forcePictureLoadForId forces the picture of the given user to be reloaded.
*/
@SuppressWarnings("unchecked")
private void refreshUsers(int forcePictureLoadForId) {
if (DEBUG)
Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId + ")");
if (forcePictureLoadForId != UserHandle.USER_NULL) {
mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
}
if (mPauseRefreshUsers) {
return;
}
boolean forceAllUsers = mForcePictureLoadForUserId.get(UserHandle.USER_ALL);
SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
final int N = mUsers.size();
for (int i = 0; i < N; i++) {
UserRecord r = mUsers.get(i);
if (r == null || r.picture == null || r.info == null || forceAllUsers || mForcePictureLoadForUserId.get(r.info.id)) {
continue;
}
bitmaps.put(r.info.id, r.picture);
}
mForcePictureLoadForUserId.clear();
final boolean addUsersWhenLocked = mAddUsersWhenLocked;
new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() {
@SuppressWarnings("unchecked")
@Override
protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
final SparseArray<Bitmap> bitmaps = params[0];
List<UserInfo> infos = mUserManager.getUsers(true);
if (infos == null) {
return null;
}
ArrayList<UserRecord> records = new ArrayList<>(infos.size());
int currentId = ActivityManager.getCurrentUser();
boolean canSwitchUsers = mUserManager.canSwitchUsers();
UserInfo currentUserInfo = null;
UserRecord guestRecord = null;
for (UserInfo info : infos) {
boolean isCurrent = currentId == info.id;
if (isCurrent) {
currentUserInfo = info;
}
boolean switchToEnabled = canSwitchUsers || isCurrent;
if (info.isEnabled()) {
if (info.isGuest()) {
// Tapping guest icon triggers remove and a user switch therefore
// the icon shouldn't be enabled even if the user is current
guestRecord = new UserRecord(info, null, /* picture */
true, /* isGuest */
isCurrent, false, /* isAddUser */
false, /* isRestricted */
canSwitchUsers);
} else if (info.supportsSwitchToByUser()) {
Bitmap picture = bitmaps.get(info.id);
if (picture == null) {
picture = mUserManager.getUserIcon(info.id);
if (picture != null) {
int avatarSize = mContext.getResources().getDimensionPixelSize(R.dimen.max_avatar_size);
picture = Bitmap.createScaledBitmap(picture, avatarSize, avatarSize, true);
}
}
int index = isCurrent ? 0 : records.size();
records.add(index, new UserRecord(info, picture, false, /* isGuest */
isCurrent, false, /* isAddUser */
false, /* isRestricted */
switchToEnabled));
}
}
}
boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
boolean currentUserCanCreateUsers = currentUserInfo != null && (currentUserInfo.isAdmin() || currentUserInfo.id == UserHandle.USER_SYSTEM) && systemCanCreateUsers;
boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked;
boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers) && guestRecord == null;
boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers) && mUserManager.canAddMoreUsers();
boolean createIsRestricted = !addUsersWhenLocked;
if (!mSimpleUserSwitcher) {
if (guestRecord == null) {
if (canCreateGuest) {
guestRecord = new UserRecord(null, /* info */
null, /* picture */
true, /* isGuest */
false, /* isCurrent */
false, /* isAddUser */
createIsRestricted, canSwitchUsers);
checkIfAddUserDisallowedByAdminOnly(guestRecord);
records.add(guestRecord);
}
} else {
int index = guestRecord.isCurrent ? 0 : records.size();
records.add(index, guestRecord);
}
}
if (!mSimpleUserSwitcher && canCreateUser) {
UserRecord addUserRecord = new UserRecord(null, /* info */
null, /* picture */
false, /* isGuest */
false, /* isCurrent */
true, /* isAddUser */
createIsRestricted, canSwitchUsers);
checkIfAddUserDisallowedByAdminOnly(addUserRecord);
records.add(addUserRecord);
}
return records;
}
@Override
protected void onPostExecute(ArrayList<UserRecord> userRecords) {
if (userRecords != null) {
mUsers = userRecords;
notifyAdapters();
}
}
}.execute((SparseArray) bitmaps);
}
use of android.util.SparseArray in project android_frameworks_base by DirtyUnicorns.
the class BatteryStats method dumpCheckinLocked.
@SuppressWarnings("unused")
public void dumpCheckinLocked(Context context, PrintWriter pw, List<ApplicationInfo> apps, int flags, long histStart) {
prepareForDumpLocked();
dumpLine(pw, 0, /* uid */
"i", /* category */
VERSION_DATA, CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion());
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
final boolean filtering = (flags & (DUMP_HISTORY_ONLY | DUMP_CHARGED_ONLY | DUMP_DAILY_ONLY)) != 0;
if ((flags & DUMP_INCLUDE_HISTORY) != 0 || (flags & DUMP_HISTORY_ONLY) != 0) {
if (startIteratingHistoryLocked()) {
try {
for (int i = 0; i < getHistoryStringPoolSize(); i++) {
pw.print(BATTERY_STATS_CHECKIN_VERSION);
pw.print(',');
pw.print(HISTORY_STRING_POOL);
pw.print(',');
pw.print(i);
pw.print(",");
pw.print(getHistoryTagPoolUid(i));
pw.print(",\"");
String str = getHistoryTagPoolString(i);
str = str.replace("\\", "\\\\");
str = str.replace("\"", "\\\"");
pw.print(str);
pw.print("\"");
pw.println();
}
dumpHistoryLocked(pw, flags, histStart, true);
} finally {
finishIteratingHistoryLocked();
}
}
}
if (filtering && (flags & (DUMP_CHARGED_ONLY | DUMP_DAILY_ONLY)) == 0) {
return;
}
if (apps != null) {
SparseArray<Pair<ArrayList<String>, MutableBoolean>> uids = new SparseArray<>();
for (int i = 0; i < apps.size(); i++) {
ApplicationInfo ai = apps.get(i);
Pair<ArrayList<String>, MutableBoolean> pkgs = uids.get(UserHandle.getAppId(ai.uid));
if (pkgs == null) {
pkgs = new Pair<>(new ArrayList<String>(), new MutableBoolean(false));
uids.put(UserHandle.getAppId(ai.uid), pkgs);
}
pkgs.first.add(ai.packageName);
}
SparseArray<? extends Uid> uidStats = getUidStats();
final int NU = uidStats.size();
String[] lineArgs = new String[2];
for (int i = 0; i < NU; i++) {
int uid = UserHandle.getAppId(uidStats.keyAt(i));
Pair<ArrayList<String>, MutableBoolean> pkgs = uids.get(uid);
if (pkgs != null && !pkgs.second.value) {
pkgs.second.value = true;
for (int j = 0; j < pkgs.first.size(); j++) {
lineArgs[0] = Integer.toString(uid);
lineArgs[1] = pkgs.first.get(j);
dumpLine(pw, 0, /* uid */
"i", /* category */
UID_DATA, (Object[]) lineArgs);
}
}
}
}
if (!filtering || (flags & DUMP_CHARGED_ONLY) != 0) {
dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
String[] lineArgs = new String[1];
long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
if (timeRemaining >= 0) {
lineArgs[0] = Long.toString(timeRemaining);
dumpLine(pw, 0, /* uid */
"i", /* category */
DISCHARGE_TIME_REMAIN_DATA, (Object[]) lineArgs);
}
dumpDurationSteps(pw, "", CHARGE_STEP_DATA, getChargeLevelStepTracker(), true);
timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
if (timeRemaining >= 0) {
lineArgs[0] = Long.toString(timeRemaining);
dumpLine(pw, 0, /* uid */
"i", /* category */
CHARGE_TIME_REMAIN_DATA, (Object[]) lineArgs);
}
dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1, (flags & DUMP_DEVICE_WIFI_ONLY) != 0);
}
}
use of android.util.SparseArray in project android_frameworks_base by DirtyUnicorns.
the class AppErrors method appNotResponding.
final void appNotResponding(ProcessRecord app, ActivityRecord activity, ActivityRecord parent, boolean aboveSystem, final String annotation) {
ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
if (mService.mController != null) {
try {
// 0 == continue, -1 = kill process immediately
int res = mService.mController.appEarlyNotResponding(app.processName, app.pid, annotation);
if (res < 0 && app.pid != MY_PID) {
app.kill("anr", true);
}
} catch (RemoteException e) {
mService.mController = null;
Watchdog.getInstance().setActivityController(null);
}
}
long anrTime = SystemClock.uptimeMillis();
if (ActivityManagerService.MONITOR_CPU_USAGE) {
mService.updateCpuStatsNow();
}
// Unless configured otherwise, swallow ANRs in background processes & kill the process.
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
boolean isSilentANR;
synchronized (mService) {
// PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
if (mService.mShuttingDown) {
Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
return;
} else if (app.notResponding) {
Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
return;
} else if (app.crashing) {
Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
return;
}
// In case we come through here for the same app before completing
// this one, mark as anring now so we will bail out.
app.notResponding = true;
// Log the ANR to the event log.
EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid, app.processName, app.info.flags, annotation);
// Dump thread traces as quickly as we can, starting with "interesting" processes.
firstPids.add(app.pid);
// Don't dump other PIDs if it's a background ANR
isSilentANR = !showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID;
if (!isSilentANR) {
int parentPid = app.pid;
if (parent != null && parent.app != null && parent.app.pid > 0) {
parentPid = parent.app.pid;
}
if (parentPid != app.pid)
firstPids.add(parentPid);
if (MY_PID != app.pid && MY_PID != parentPid)
firstPids.add(MY_PID);
for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mService.mLruProcesses.get(i);
if (r != null && r.thread != null) {
int pid = r.pid;
if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
if (r.persistent) {
firstPids.add(pid);
if (DEBUG_ANR)
Slog.i(TAG, "Adding persistent proc: " + r);
} else {
lastPids.put(pid, Boolean.TRUE);
if (DEBUG_ANR)
Slog.i(TAG, "Adding ANR proc: " + r);
}
}
}
}
}
}
// Log the ANR to the main log.
StringBuilder info = new StringBuilder();
info.setLength(0);
info.append("ANR in ").append(app.processName);
if (activity != null && activity.shortComponentName != null) {
info.append(" (").append(activity.shortComponentName).append(")");
}
info.append("\n");
info.append("PID: ").append(app.pid).append("\n");
if (annotation != null) {
info.append("Reason: ").append(annotation).append("\n");
}
if (parent != null && parent != activity) {
info.append("Parent: ").append(parent.shortComponentName).append("\n");
}
ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
String[] nativeProcs = NATIVE_STACKS_OF_INTEREST;
// don't dump native PIDs for background ANRs
File tracesFile = null;
if (isSilentANR) {
tracesFile = mService.dumpStackTraces(true, firstPids, null, lastPids, null);
} else {
tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids, nativeProcs);
}
String cpuInfo = null;
if (ActivityManagerService.MONITOR_CPU_USAGE) {
mService.updateCpuStatsNow();
synchronized (mService.mProcessCpuTracker) {
cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
}
info.append(processCpuTracker.printCurrentLoad());
info.append(cpuInfo);
}
info.append(processCpuTracker.printCurrentState(anrTime));
Slog.e(TAG, info.toString());
if (tracesFile == null) {
// There is no trace file, so dump (only) the alleged culprit's threads to the log
Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
}
mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation, cpuInfo, tracesFile, null);
if (mService.mController != null) {
try {
// 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
int res = mService.mController.appNotResponding(app.processName, app.pid, info.toString());
if (res != 0) {
if (res < 0 && app.pid != MY_PID) {
app.kill("anr", true);
} else {
synchronized (mService) {
mService.mServices.scheduleServiceTimeoutLocked(app);
}
}
return;
}
} catch (RemoteException e) {
mService.mController = null;
Watchdog.getInstance().setActivityController(null);
}
}
synchronized (mService) {
mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
if (isSilentANR) {
app.kill("bg anr", true);
return;
}
// Set the app's notResponding state, and look up the errorReportReceiver
makeAppNotRespondingLocked(app, activity != null ? activity.shortComponentName : null, annotation != null ? "ANR " + annotation : "ANR", info.toString());
// Bring up the infamous App Not Responding dialog
Message msg = Message.obtain();
HashMap<String, Object> map = new HashMap<String, Object>();
msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
msg.obj = map;
msg.arg1 = aboveSystem ? 1 : 0;
map.put("app", app);
if (activity != null) {
map.put("activity", activity);
}
mService.mUiHandler.sendMessage(msg);
}
}
Aggregations