• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  *      http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 
15 #include "tuningfork/protobuf_util.h"
16 #include "tuningfork/tuningfork_extra.h"
17 #include "swappy/swappy.h"
18 #include "full/tuningfork.pb.h"
19 #include "full/tuningfork_clearcut_log.pb.h"
20 #include "full/dev_tuningfork.pb.h"
21 #include <sstream>
22 #include <jni.h>
23 #include <android/native_window_jni.h>
24 
25 #define LOG_TAG "tftestapp"
26 #include "Log.h"
27 #include "Renderer.h"
28 
29 using ::com::google::tuningfork::FidelityParams;
30 using ::com::google::tuningfork::Settings;
31 using ::com::google::tuningfork::Annotation;
32 using ::logs::proto::tuningfork::TuningForkLogEvent;
33 using ::logs::proto::tuningfork::TuningForkHistogram;
34 
35 namespace proto_tf = com::google::tuningfork;
36 namespace tf = tuningfork;
37 using namespace samples;
38 
39 bool swappy_enabled = false;
40 
41 namespace {
42 
43 constexpr TFInstrumentKey TFTICK_CHOREOGRAPHER = 4;
44 
45 struct HistogramSettings {
46     float start, end;
47     int nBuckets;
48 };
TestSettings(Settings::AggregationStrategy::Submission method,int n_ticks,int n_keys,std::vector<int> annotation_size,const std::vector<HistogramSettings> & hists={})49 Settings TestSettings(Settings::AggregationStrategy::Submission method, int n_ticks, int n_keys,
50                       std::vector<int> annotation_size,
51                       const std::vector<HistogramSettings>& hists = {}) {
52     // Make sure we set all required fields
53     Settings s;
54     s.mutable_aggregation_strategy()->set_method(method);
55     s.mutable_aggregation_strategy()->set_intervalms_or_count(n_ticks);
56     s.mutable_aggregation_strategy()->set_max_instrumentation_keys(n_keys);
57     for(int i=0;i<annotation_size.size();++i)
58         s.mutable_aggregation_strategy()->add_annotation_enum_size(annotation_size[i]);
59     int i=0;
60     for(auto& h: hists) {
61         auto sh = s.add_histograms();
62         sh->set_bucket_min(h.start);
63         sh->set_bucket_max(h.end);
64         sh->set_n_buckets(h.nBuckets);
65         sh->set_instrument_key(i++);
66     }
67     return s;
68 }
69 
ReplaceReturns(const std::string & s)70 std::string ReplaceReturns(const std::string& s) {
71     std::string r = s;
72     for (int i=0; i<r.length(); ++i) {
73         if (r[i]=='\n') r[i] = ',';
74         if (r[i]=='\r') r[i] = ' ';
75     }
76     return r;
77 }
78 
PrettyPrintTuningForkLogEvent(const TuningForkLogEvent & evt)79 std::string PrettyPrintTuningForkLogEvent(const TuningForkLogEvent& evt) {
80     std::stringstream eventStr;
81     eventStr << "TuningForkLogEvent {\n";
82     if (evt.has_fidelityparams()) {
83         FidelityParams p;
84         p.ParseFromArray(evt.fidelityparams().c_str(), evt.fidelityparams().length());
85         eventStr << "  fidelityparams : " << ReplaceReturns(p.DebugString()) << "\n";
86     }
87     for (int i=0; i<evt.histograms_size(); ++i) {
88         auto &h = evt.histograms(i);
89         Annotation ann;
90         ann.ParseFromArray(h.annotation().c_str(), h.annotation().length());
91         bool first = true;
92         eventStr << "  histogram {\n";
93         eventStr << "    instrument_id : " << h.instrument_id() << "\n";
94         eventStr << "    annotation : " << ReplaceReturns(ann.DebugString()) << "\n    counts : ";
95         eventStr << "[";
96         for (int j=0; j<h.counts_size(); ++j) {
97             if (first) {
98                 first = false;
99             } else {
100                 eventStr << ",";
101             }
102             eventStr << h.counts(j);
103         }
104         eventStr << "]\n  }\n";
105     }
106     if (evt.has_experiment_id()) {
107         eventStr << "  experiment_id : " << evt.experiment_id() << "\n";
108     }
109     if (evt.has_session_id()) {
110         eventStr << "  session_id : " << evt.session_id() << "\n";
111     }
112     if (evt.has_device_info()) {
113         eventStr << "  device_info : {" << ReplaceReturns(evt.device_info().DebugString()) << "}\n";
114     }
115     if (evt.has_apk_package_name()) {
116         eventStr << "  apk_package_name : " << evt.apk_package_name() << "\n";
117     }
118     if (evt.has_apk_version_code()) {
119         eventStr << "  apk_version_code : " << evt.apk_version_code() << "\n";
120     }
121     if (evt.has_tuningfork_version()) {
122         eventStr << "  tuningfork_version : " << evt.tuningfork_version() << "\n";
123     }
124     eventStr << "}";
125     return eventStr.str();
126 }
SplitAndLog(const std::string & s)127 void SplitAndLog(const std::string& s) {
128     std::istringstream str(s);
129     std::string line;
130     std::stringstream to_log;
131     const int nlines_per_log = 16;
132     int l = nlines_per_log;
133     while (std::getline(str, line, '\n')) {
134         to_log << line << '\n';
135         if(--l<=0) {
136             ALOGI("%s", to_log.str().c_str());
137             l = nlines_per_log;
138             to_log.str("");
139         }
140     }
141     if (to_log.str().length()>0)
142         ALOGI("%s", to_log.str().c_str());
143 }
144 
UploadCallback(const CProtobufSerialization * tuningfork_log_event)145 void UploadCallback(const CProtobufSerialization *tuningfork_log_event) {
146     if(tuningfork_log_event) {
147         TuningForkLogEvent evt;
148         evt.ParseFromArray(tuningfork_log_event->bytes, tuningfork_log_event->size);
149         auto pp = PrettyPrintTuningForkLogEvent(evt);
150         SplitAndLog(pp);
151     }
152 }
153 
154 static int sLevel = proto_tf::LEVEL_1;
155 extern "C"
SetAnnotations()156 void SetAnnotations() {
157     if(proto_tf::Level_IsValid(sLevel)) {
158         Annotation a;
159         a.set_level((proto_tf::Level)sLevel);
160         auto next_level = sLevel + 1;
161         a.set_next_level((proto_tf::Level)(next_level>proto_tf::Level_MAX?1:next_level));
162         auto ser = tf::CProtobufSerialization_Alloc(a);
163         TuningFork_setCurrentAnnotation(&ser);
164         tf::CProtobufSerialization_Free(&ser);
165     }
166 }
167 
SetFidelityParams(const CProtobufSerialization * params)168 void SetFidelityParams(const CProtobufSerialization* params) {
169     FidelityParams p;
170     // Set default values
171     p.set_num_spheres(20);
172     p.set_tesselation_percent(50);
173     std::vector<uint8_t> params_ser(params->bytes, params->bytes + params->size);
174     tf::Deserialize(params_ser, p);
175     std::string s = p.DebugString();
176     ALOGI("Using FidelityParams: %s", ReplaceReturns(s).c_str());
177     int nSpheres = p.num_spheres();
178     int tesselation = p.tesselation_percent();
179     Renderer::getInstance()->setQuality(nSpheres, tesselation);
180 }
181 
182 } // anonymous namespace
183 
184 extern "C" {
185 
186 JNIEXPORT void JNICALL
Java_com_google_tuningfork_TFTestActivity_initTuningFork(JNIEnv * env,jobject activity)187 Java_com_google_tuningfork_TFTestActivity_initTuningFork(JNIEnv *env, jobject activity) {
188     Swappy_init(env, activity);
189     swappy_enabled = Swappy_isEnabled();
190     if (swappy_enabled) {
191         int defaultFPIndex = 3; // i.e. dev_tuningfork_fidelityparams_3.bin
192         int initialTimeoutMs = 1000;
193         int ultimateTimeoutMs = 100000;
194         TFErrorCode c = TuningFork_initFromAssetsWithSwappy(env, activity, "libnative-lib.so",
195                                                     SetAnnotations, defaultFPIndex,
196                                                     SetFidelityParams,
197                                                     initialTimeoutMs, ultimateTimeoutMs);
198         if (c==TFERROR_OK) {
199             TuningFork_setUploadCallback(UploadCallback);
200             SetAnnotations();
201         } else {
202             ALOGW("Error initializing TuningFork: %d", c);
203         }
204     } else {
205         ALOGW("Couldn't enable Swappy.");
206         CProtobufSerialization settings = {};
207         TuningFork_findSettingsInAPK(env, activity, &settings);
208         TuningFork_init(&settings, env, activity);
209         tuningfork::CProtobufSerialization_Free(&settings);
210         int fp_count;
211         TuningFork_findFidelityParamsInAPK(env, activity, NULL, &fp_count);
212         CProtobufSerialization fps = {};
213         std::vector<CProtobufSerialization> defaultFPs(fp_count);
214         TuningFork_findFidelityParamsInAPK(env, activity, defaultFPs.data(), &fp_count);
215         CProtobufSerialization* defaultFP = &defaultFPs[fp_count/2-1]; // Middle settings level
216         if (TuningFork_getFidelityParameters(defaultFP, &fps, 1000)) {
217             SetFidelityParams(&fps);
218             tuningfork::CProtobufSerialization_Free(&fps);
219         }
220         else {
221             SetFidelityParams(defaultFP);
222         }
223         for(auto& a: defaultFPs) {
224             tuningfork::CProtobufSerialization_Free(&a);
225         }
226         TuningFork_setUploadCallback(UploadCallback);
227         SetAnnotations();
228     }
229 }
230 
231 JNIEXPORT void JNICALL
Java_com_google_tuningfork_TFTestActivity_onChoreographer(JNIEnv *,jclass clz,jlong)232 Java_com_google_tuningfork_TFTestActivity_onChoreographer(JNIEnv */*env*/, jclass clz, jlong /*frameTimeNanos*/) {
233     TuningFork_frameTick(TFTICK_CHOREOGRAPHER);
234     // After 600 ticks, switch to the next level
235     static int tick_count = 0;
236     ++tick_count;
237     if(tick_count>=600) {
238         ++sLevel;
239         if(sLevel>proto_tf::Level_MAX) sLevel = proto_tf::LEVEL_1;
240         SetAnnotations();
241         tick_count = 0;
242     }
243 }
244 JNIEXPORT void JNICALL
Java_com_google_tuningfork_TFTestActivity_resize(JNIEnv * env,jclass,jobject surface,jint width,jint height)245 Java_com_google_tuningfork_TFTestActivity_resize(JNIEnv *env, jclass /*clz*/, jobject surface, jint width, jint height) {
246     ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
247     Renderer::getInstance()->setWindow(window,
248                                        static_cast<int32_t>(width),
249                                        static_cast<int32_t>(height));
250 }
251 JNIEXPORT void JNICALL
Java_com_google_tuningfork_TFTestActivity_clearSurface(JNIEnv *,jclass)252 Java_com_google_tuningfork_TFTestActivity_clearSurface(JNIEnv */*env*/, jclass /*clz*/ ) {
253     Renderer::getInstance()->setWindow(nullptr, 0, 0);
254 }
255 JNIEXPORT void JNICALL
Java_com_google_tuningfork_TFTestActivity_start(JNIEnv *,jclass)256 Java_com_google_tuningfork_TFTestActivity_start(JNIEnv */*env*/, jclass /*clz*/ ) {
257     Renderer::getInstance()->start();
258 }
259 JNIEXPORT void JNICALL
Java_com_google_tuningfork_TFTestActivity_stop(JNIEnv *,jclass)260 Java_com_google_tuningfork_TFTestActivity_stop(JNIEnv */*env*/, jclass /*clz*/ ) {
261     Renderer::getInstance()->stop();
262 }
263 
264 }
265