Loading services/backup/java/com/android/server/backup/BackupManagerService.java +5 −2 Original line number Diff line number Diff line Loading @@ -3525,7 +3525,10 @@ public class BackupManagerService implements BackupManagerServiceInterface { dumpAgents(pw); return; } else if ("transportclients".equals(arg.toLowerCase())) { mTransportManager.dump(pw); mTransportManager.dumpTransportClients(pw); return; } else if ("transportstats".equals(arg.toLowerCase())) { mTransportManager.dumpTransportStats(pw); return; } } Loading Loading @@ -3590,7 +3593,7 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } mTransportManager.dump(pw); mTransportManager.dumpTransportClients(pw); pw.println("Pending init: " + mPendingInits.size()); for (String s : mPendingInits) { Loading services/backup/java/com/android/server/backup/TransportManager.java +14 −2 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.server.backup.transport.TransportClientManager; import com.android.server.backup.transport.TransportConnectionListener; import com.android.server.backup.transport.TransportNotAvailableException; import com.android.server.backup.transport.TransportNotRegisteredException; import com.android.server.backup.transport.TransportStats; import java.io.PrintWriter; import java.util.List; Loading @@ -64,6 +65,7 @@ public class TransportManager { private final PackageManager mPackageManager; private final Set<ComponentName> mTransportWhitelist; private final TransportClientManager mTransportClientManager; private final TransportStats mTransportStats; private OnTransportRegisteredListener mOnTransportRegisteredListener = (c, n) -> {}; /** Loading @@ -85,7 +87,12 @@ public class TransportManager { private volatile String mCurrentTransportName; TransportManager(Context context, Set<ComponentName> whitelist, String selectedTransport) { this(context, whitelist, selectedTransport, new TransportClientManager(context)); mContext = context; mPackageManager = context.getPackageManager(); mTransportWhitelist = Preconditions.checkNotNull(whitelist); mCurrentTransportName = selectedTransport; mTransportStats = new TransportStats(); mTransportClientManager = new TransportClientManager(context, mTransportStats); } @VisibleForTesting Loading @@ -98,6 +105,7 @@ public class TransportManager { mPackageManager = context.getPackageManager(); mTransportWhitelist = Preconditions.checkNotNull(whitelist); mCurrentTransportName = selectedTransport; mTransportStats = new TransportStats(); mTransportClientManager = transportClientManager; } Loading Loading @@ -640,10 +648,14 @@ public class TransportManager { !Thread.holdsLock(mTransportLock), "Can't call transport with transport lock held"); } public void dump(PrintWriter pw) { public void dumpTransportClients(PrintWriter pw) { mTransportClientManager.dump(pw); } public void dumpTransportStats(PrintWriter pw) { mTransportStats.dump(pw); } private static Predicate<ComponentName> fromPackageFilter(String packageName) { return transportComponent -> packageName.equals(transportComponent.getPackageName()); } Loading services/backup/java/com/android/server/backup/transport/TransportClient.java +13 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.os.DeadObjectException; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.SystemClock; import android.os.UserHandle; import android.text.format.DateFormat; import android.util.ArrayMap; Loading @@ -51,6 +52,7 @@ import java.lang.ref.WeakReference; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; Loading Loading @@ -78,6 +80,7 @@ public class TransportClient { private static final int LOG_BUFFER_SIZE = 5; private final Context mContext; private final TransportStats mTransportStats; private final Intent mBindIntent; private final ServiceConnection mConnection; private final String mIdentifier; Loading @@ -104,12 +107,14 @@ public class TransportClient { TransportClient( Context context, TransportStats transportStats, Intent bindIntent, ComponentName transportComponent, String identifier, String caller) { this( context, transportStats, bindIntent, transportComponent, identifier, Loading @@ -120,12 +125,14 @@ public class TransportClient { @VisibleForTesting TransportClient( Context context, TransportStats transportStats, Intent bindIntent, ComponentName transportComponent, String identifier, String caller, Handler listenerHandler) { mContext = context; mTransportStats = transportStats; mTransportComponent = transportComponent; mBindIntent = bindIntent; mIdentifier = identifier; Loading Loading @@ -321,11 +328,16 @@ public class TransportClient { (requestedTransport, transportClient) -> transportFuture.complete(requestedTransport); long requestTime = SystemClock.elapsedRealtime(); log(Priority.DEBUG, caller, "Sync connect: calling async"); connectAsync(requestListener, caller); try { return transportFuture.get(); transport = transportFuture.get(); long time = SystemClock.elapsedRealtime() - requestTime; mTransportStats.registerConnectionTime(mTransportComponent, time); log(Priority.DEBUG, caller, String.format(Locale.US, "Connect took %d ms", time)); return transport; } catch (InterruptedException | ExecutionException e) { String error = e.getClass().getSimpleName(); log(Priority.ERROR, caller, error + " while waiting for transport: " + e.getMessage()); Loading services/backup/java/com/android/server/backup/transport/TransportClientManager.java +4 −1 Original line number Diff line number Diff line Loading @@ -37,12 +37,14 @@ public class TransportClientManager { private static final String TAG = "TransportClientManager"; private final Context mContext; private final TransportStats mTransportStats; private final Object mTransportClientsLock = new Object(); private int mTransportClientsCreated = 0; private Map<TransportClient, String> mTransportClientsCallerMap = new WeakHashMap<>(); public TransportClientManager(Context context) { public TransportClientManager(Context context, TransportStats transportStats) { mContext = context; mTransportStats = transportStats; } /** Loading Loading @@ -88,6 +90,7 @@ public class TransportClientManager { TransportClient transportClient = new TransportClient( mContext, mTransportStats, bindIntent, transportComponent, Integer.toString(mTransportClientsCreated), Loading services/backup/java/com/android/server/backup/transport/TransportStats.java 0 → 100644 +122 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.backup.transport; import android.annotation.Nullable; import android.content.ComponentName; import java.io.PrintWriter; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Optional; /** Responsible for aggregating {@link TransportClient} relevant times. */ public class TransportStats { private final Object mStatsLock = new Object(); private final Map<ComponentName, Stats> mTransportStats = new HashMap<>(); void registerConnectionTime(ComponentName transportComponent, long timeMs) { synchronized (mStatsLock) { mTransportStats .computeIfAbsent(transportComponent, name -> new Stats()) .register(timeMs); } } /** Returns {@link Stats} for transport whose host service is {@code transportComponent}. */ @Nullable public Stats getStatsForTransport(ComponentName transportComponent) { synchronized (mStatsLock) { Stats stats = mTransportStats.get(transportComponent); if (stats == null) { return null; } return new Stats(stats); } } public void dump(PrintWriter pw) { synchronized (mStatsLock) { Optional<Stats> aggregatedStats = mTransportStats.values().stream().reduce(Stats::merge); if (aggregatedStats.isPresent()) { dumpStats(pw, "", aggregatedStats.get()); } if (!mTransportStats.isEmpty()) { pw.println("Per transport:"); for (ComponentName transportComponent : mTransportStats.keySet()) { Stats stats = mTransportStats.get(transportComponent); pw.println(" " + transportComponent.flattenToShortString()); dumpStats(pw, " ", stats); } } } } private static void dumpStats(PrintWriter pw, String prefix, Stats stats) { pw.println( String.format( Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.mAverage)); pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.mMax)); pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.mMin)); pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.mN)); } public static final class Stats { public static Stats merge(Stats a, Stats b) { return new Stats( a.mN + b.mN, (a.mAverage * a.mN + b.mAverage * b.mN) / (a.mN + b.mN), Math.max(a.mMax, b.mMax), Math.min(a.mMin, b.mMin)); } public int mN; public double mAverage; public long mMax; public long mMin; public Stats() { mN = 0; mAverage = 0; mMax = 0; mMin = Long.MAX_VALUE; } private Stats(Stats original) { mN = original.mN; mAverage = original.mAverage; mMax = original.mMax; mMin = original.mMin; } private Stats(int n, double average, long max, long min) { mN = n; mAverage = average; mMax = max; mMin = min; } private void register(long sample) { mAverage = (mAverage * mN + sample) / (mN + 1); mN++; mMax = Math.max(mMax, sample); mMin = Math.min(mMin, sample); } } } Loading
services/backup/java/com/android/server/backup/BackupManagerService.java +5 −2 Original line number Diff line number Diff line Loading @@ -3525,7 +3525,10 @@ public class BackupManagerService implements BackupManagerServiceInterface { dumpAgents(pw); return; } else if ("transportclients".equals(arg.toLowerCase())) { mTransportManager.dump(pw); mTransportManager.dumpTransportClients(pw); return; } else if ("transportstats".equals(arg.toLowerCase())) { mTransportManager.dumpTransportStats(pw); return; } } Loading Loading @@ -3590,7 +3593,7 @@ public class BackupManagerService implements BackupManagerServiceInterface { } } mTransportManager.dump(pw); mTransportManager.dumpTransportClients(pw); pw.println("Pending init: " + mPendingInits.size()); for (String s : mPendingInits) { Loading
services/backup/java/com/android/server/backup/TransportManager.java +14 −2 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.server.backup.transport.TransportClientManager; import com.android.server.backup.transport.TransportConnectionListener; import com.android.server.backup.transport.TransportNotAvailableException; import com.android.server.backup.transport.TransportNotRegisteredException; import com.android.server.backup.transport.TransportStats; import java.io.PrintWriter; import java.util.List; Loading @@ -64,6 +65,7 @@ public class TransportManager { private final PackageManager mPackageManager; private final Set<ComponentName> mTransportWhitelist; private final TransportClientManager mTransportClientManager; private final TransportStats mTransportStats; private OnTransportRegisteredListener mOnTransportRegisteredListener = (c, n) -> {}; /** Loading @@ -85,7 +87,12 @@ public class TransportManager { private volatile String mCurrentTransportName; TransportManager(Context context, Set<ComponentName> whitelist, String selectedTransport) { this(context, whitelist, selectedTransport, new TransportClientManager(context)); mContext = context; mPackageManager = context.getPackageManager(); mTransportWhitelist = Preconditions.checkNotNull(whitelist); mCurrentTransportName = selectedTransport; mTransportStats = new TransportStats(); mTransportClientManager = new TransportClientManager(context, mTransportStats); } @VisibleForTesting Loading @@ -98,6 +105,7 @@ public class TransportManager { mPackageManager = context.getPackageManager(); mTransportWhitelist = Preconditions.checkNotNull(whitelist); mCurrentTransportName = selectedTransport; mTransportStats = new TransportStats(); mTransportClientManager = transportClientManager; } Loading Loading @@ -640,10 +648,14 @@ public class TransportManager { !Thread.holdsLock(mTransportLock), "Can't call transport with transport lock held"); } public void dump(PrintWriter pw) { public void dumpTransportClients(PrintWriter pw) { mTransportClientManager.dump(pw); } public void dumpTransportStats(PrintWriter pw) { mTransportStats.dump(pw); } private static Predicate<ComponentName> fromPackageFilter(String packageName) { return transportComponent -> packageName.equals(transportComponent.getPackageName()); } Loading
services/backup/java/com/android/server/backup/transport/TransportClient.java +13 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.os.DeadObjectException; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.SystemClock; import android.os.UserHandle; import android.text.format.DateFormat; import android.util.ArrayMap; Loading @@ -51,6 +52,7 @@ import java.lang.ref.WeakReference; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; Loading Loading @@ -78,6 +80,7 @@ public class TransportClient { private static final int LOG_BUFFER_SIZE = 5; private final Context mContext; private final TransportStats mTransportStats; private final Intent mBindIntent; private final ServiceConnection mConnection; private final String mIdentifier; Loading @@ -104,12 +107,14 @@ public class TransportClient { TransportClient( Context context, TransportStats transportStats, Intent bindIntent, ComponentName transportComponent, String identifier, String caller) { this( context, transportStats, bindIntent, transportComponent, identifier, Loading @@ -120,12 +125,14 @@ public class TransportClient { @VisibleForTesting TransportClient( Context context, TransportStats transportStats, Intent bindIntent, ComponentName transportComponent, String identifier, String caller, Handler listenerHandler) { mContext = context; mTransportStats = transportStats; mTransportComponent = transportComponent; mBindIntent = bindIntent; mIdentifier = identifier; Loading Loading @@ -321,11 +328,16 @@ public class TransportClient { (requestedTransport, transportClient) -> transportFuture.complete(requestedTransport); long requestTime = SystemClock.elapsedRealtime(); log(Priority.DEBUG, caller, "Sync connect: calling async"); connectAsync(requestListener, caller); try { return transportFuture.get(); transport = transportFuture.get(); long time = SystemClock.elapsedRealtime() - requestTime; mTransportStats.registerConnectionTime(mTransportComponent, time); log(Priority.DEBUG, caller, String.format(Locale.US, "Connect took %d ms", time)); return transport; } catch (InterruptedException | ExecutionException e) { String error = e.getClass().getSimpleName(); log(Priority.ERROR, caller, error + " while waiting for transport: " + e.getMessage()); Loading
services/backup/java/com/android/server/backup/transport/TransportClientManager.java +4 −1 Original line number Diff line number Diff line Loading @@ -37,12 +37,14 @@ public class TransportClientManager { private static final String TAG = "TransportClientManager"; private final Context mContext; private final TransportStats mTransportStats; private final Object mTransportClientsLock = new Object(); private int mTransportClientsCreated = 0; private Map<TransportClient, String> mTransportClientsCallerMap = new WeakHashMap<>(); public TransportClientManager(Context context) { public TransportClientManager(Context context, TransportStats transportStats) { mContext = context; mTransportStats = transportStats; } /** Loading Loading @@ -88,6 +90,7 @@ public class TransportClientManager { TransportClient transportClient = new TransportClient( mContext, mTransportStats, bindIntent, transportComponent, Integer.toString(mTransportClientsCreated), Loading
services/backup/java/com/android/server/backup/transport/TransportStats.java 0 → 100644 +122 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.backup.transport; import android.annotation.Nullable; import android.content.ComponentName; import java.io.PrintWriter; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Optional; /** Responsible for aggregating {@link TransportClient} relevant times. */ public class TransportStats { private final Object mStatsLock = new Object(); private final Map<ComponentName, Stats> mTransportStats = new HashMap<>(); void registerConnectionTime(ComponentName transportComponent, long timeMs) { synchronized (mStatsLock) { mTransportStats .computeIfAbsent(transportComponent, name -> new Stats()) .register(timeMs); } } /** Returns {@link Stats} for transport whose host service is {@code transportComponent}. */ @Nullable public Stats getStatsForTransport(ComponentName transportComponent) { synchronized (mStatsLock) { Stats stats = mTransportStats.get(transportComponent); if (stats == null) { return null; } return new Stats(stats); } } public void dump(PrintWriter pw) { synchronized (mStatsLock) { Optional<Stats> aggregatedStats = mTransportStats.values().stream().reduce(Stats::merge); if (aggregatedStats.isPresent()) { dumpStats(pw, "", aggregatedStats.get()); } if (!mTransportStats.isEmpty()) { pw.println("Per transport:"); for (ComponentName transportComponent : mTransportStats.keySet()) { Stats stats = mTransportStats.get(transportComponent); pw.println(" " + transportComponent.flattenToShortString()); dumpStats(pw, " ", stats); } } } } private static void dumpStats(PrintWriter pw, String prefix, Stats stats) { pw.println( String.format( Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.mAverage)); pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.mMax)); pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.mMin)); pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.mN)); } public static final class Stats { public static Stats merge(Stats a, Stats b) { return new Stats( a.mN + b.mN, (a.mAverage * a.mN + b.mAverage * b.mN) / (a.mN + b.mN), Math.max(a.mMax, b.mMax), Math.min(a.mMin, b.mMin)); } public int mN; public double mAverage; public long mMax; public long mMin; public Stats() { mN = 0; mAverage = 0; mMax = 0; mMin = Long.MAX_VALUE; } private Stats(Stats original) { mN = original.mN; mAverage = original.mAverage; mMax = original.mMax; mMin = original.mMin; } private Stats(int n, double average, long max, long min) { mN = n; mAverage = average; mMax = max; mMin = min; } private void register(long sample) { mAverage = (mAverage * mN + sample) / (mN + 1); mN++; mMax = Math.max(mMax, sample); mMin = Math.min(mMin, sample); } } }